Compare commits

...

487 commits

Author SHA1 Message Date
rjl493456442
ca1f2e4d38
core: fix tx size calculation (#35406)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
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.
2026-07-24 10:50:20 +02:00
cui
cd65ccad96
eth/downloader: hold pivotLock when marking pivot committed (#35405)
commitPivotBlock updated committed without pivotLock, while other pivot
transitions serialize through that lock. Take the lock around the store
to keep pivot commitment consistent with pivotHeader updates.
2026-07-24 16:19:35 +08:00
rjl493456442
a524f2bb17
node: check authorization header case-insensitivity (#35408) 2026-07-24 16:19:14 +08:00
cui
af03a271df
cmd/utils: skip memory-limit sanitize when total memory is unknown (#35407) 2026-07-24 15:48:40 +08:00
Jonny Rhea
ff44a796a1
core: coordinate the state prefetcher with block processing (#35404)
This PR coordinates the prefetcher with the main tx executor. Block
processing publishes the index of the transaction it is executing,
prefetch workers skip anything already reached and transactions above 1M
gas are promoted to the front of the prefetch queue while the rest keeps
block order.
2026-07-24 15:43:46 +08:00
cui
b2ee83931b
eth/catalyst: allow reorg depth equal to maxReorgDepth (#35391)
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
The deep-reorg check used depth >= maxReorgDepth, rejecting reorgs at
exactly the configured limit. Use > so a depth equal to maxReorgDepth is
still accepted.
2026-07-23 22:49:48 +08:00
rjl493456442
f03b91cf28
core: optimize block validation (#35403)
This PR parallelizes the block validation alongside the IntermediateRoot, 
saving the time spent on the receiptRoot hashing, BAL hashing and so on.
2026-07-23 22:49:01 +08:00
cui
e317407d16
eth/fetcher: clear partial map when dropping last waitlist peer (#35399)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Docker Image (push) Waiting to run
When a peer drop removes the last waiter for a hash, waitlist and
waittime were cleaned up but partial could retain a stale entry. Delete
it too so the hash is fully forgotten.
2026-07-23 10:22:47 +02:00
rjl493456442
81ab8b594e
eth/downloader: disable snap mode after committing pivot block (#35402)
This PR improves the sync mode management, disabling the snap mode once 
the pivot block is committed. 

Originally the mode will only be flipped from snap to full once the entire sync 
cycle is completed. However, it's theoretically possible to cancel the sync cycle
after committing the pivot but before inserting the remaining blocks. It drags
the following sync cycle back to the snap mode.

The snap mode should only be used if the head state is missing and unrecoverable. 
Enabling the snap mode for multiple times should be strictly prevented.

What's more, it brings a fix to pivot block management, that once the
pivot block is committed, the pivot block marker should be no longer advanced,
preventing the situation that the real pivot state is below the pivot marker.
2026-07-23 14:30:20 +08:00
Jonny Rhea
8e8003acd3
triedb/pathdb: report nothing recoverable during state sync (#35400)
Restarting a node mid-snap-sync can crash-loop during startup chain
repair. On a restart mid-sync the pathdb is disabled (`waitSync`), so
repair rewinds the stateless head to genesis and asks `StateRecoverable`
if it can roll back there. `Recoverable` doesn't check `waitSync`, so it
reports genesis as recoverable, but `Recover` does and refuses with
`waiting for sync`, tripping a `log.Crit`. The flag is persisted, so the
node crash-loops on every restart.

CRIT Failed to recover state number=0 hash=37fcdc..6edf0b err="waiting
for sync"

The fix is to make `Recoverable` return false while a sync is running,
so it agrees with `Recover`. Repair then falls through to the existing
"wait state sync" path.
2026-07-23 14:26:01 +08:00
rjl493456442
c767f825c5
cmd: add gogc flag (#35363)
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 adds the CLI flag gogc for twisting the garbage collection
target. The default value is chosen as the 50, balancing the 
performance gain and potential memory peak.
2026-07-23 11:07:42 +08:00
cui
a9ca080d7f
eth/fetcher: count unique hashes in blob queueing metric (#35393)
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
blobFetcherQueueingHashes used len(announces), which is the number of
peers with pending announces, not the number of queued hashes. Count
unique hashes across peers instead.

---------

Co-authored-by: Bosul Mun <bsbs8645@snu.ac.kr>
2026-07-22 13:20:43 +02:00
Marius van der Wijden
5d88c6b324
core: fix tracer panic (#35396)
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
Now with 8037, there are transactions that fail AFTER intrinsic gas but
BEFORE Call or Create operation. These will currently result in a panic
in tracing, since they produce a receipt

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-07-22 11:37:28 +08:00
rjl493456442
6e49f8e6b3
core: improve amsterdam fork test coverage (#35364)
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
Improve test coverage for amsterdam EIPs
2026-07-21 11:02:02 +08:00
0xoasis
85fe272355
core/txpool/blobpool: serialize legacy data conversions (#35387)
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
`conversionQueue` is meant to run billy/legacy migrations serially on a
single worker. On each `startConversion`, it currently always calls
`runNextTask()`, which overwrites `taskDone` and starts another
goroutine even when a migration is already running.

That breaks two invariants during an upgrade with legacy entries in both
the main store and limbo:

1. Migrations intended to be serial can run concurrently.
2. `close()` only waits for the most recently launched task, so shutdown
can close the stores while a forgotten migration is still using them.

Only start the next queued migration when no task is active (`taskDone
== nil`). The existing `taskDone` completion path then advances the
queue, and `close` reliably waits for the active task.
2026-07-20 19:25:57 +02:00
rjl493456442
47450f97fc
core/vm: initialize the bogota instructions from Amsterdam (#35383) 2026-07-20 09:12:35 -05:00
0xoasis
a38a90bc60
eth/protocols/eth: track announced tx hashes only after send (#35384)
Commit 1f87331fb moved the known-transaction marking in
`sendPooledTransactionHashes` to after a successful send, so hashes are
not marked known to the peer if the announcement fails to go out.

The sparse blobpool change (d91b71fb3) reintroduced the original
track-before-send ordering when adding the eth/72 packet variant,
causing failed announcements to suppress future re-announcements of the
same hashes to that peer.

This restores the send-first ordering for both eth/71 and eth/72 packet
versions, and adds a regression test covering success and failure paths
on both protocol versions.

## Checklist

- [x] Restored mark-known-after-send for ETH71 and ETH72
- [x] Added `TestSendPooledTransactionHashes` covering success and
closed-pipe failure

---------

Co-authored-by: Bosul Mun <bsbs8645@snu.ac.kr>
2026-07-20 15:40:04 +02:00
Marius van der Wijden
4363b81e6f
eth/catalyst: pass TargetGasLimit via engine api (#35372)
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
Pass targetGasLimit via engine api

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-07-20 15:08:23 +08:00
0xoasis
4911ab04fc
cmd/geth, eth/ethconfig: preserve zero engine reorg depth (#35373)
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-07-20 10:53:19 +08:00
Jonny Rhea
bb6401ee5f
miner, core: reuse the chain's jumpdest cache when building payloads (#35378)
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
Follow-up to #34850. The miner's payload EVM previously used a private
per-EVM JUMPDEST map, so every ~2s payload rebuild re-analyzed the code
bitmap of every contract the block touches.
2026-07-18 17:38:24 -05:00
rjl493456442
dddbaa4bf3
cmd/utils: export chain with block-level accessList (#35369)
Some checks failed
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Linux Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
2026-07-17 18:54:07 +02:00
ozpool
80b58f649a
cmd/devp2p/internal/ethtest: fix header stride in reverse GetHeaders (#35362)
`Chain.GetHeaders` steps by `1 + Skip` in the forward branch but by `1 -
Skip` in the reverse branch. `Skip` is a `uint64`, so the reverse stride
is wrong for every `Skip > 0`:

| Skip | reverse step | result |
| --- | --- | --- |
| 0 | `-= 1` | correct |
| 1 | `-= 0` | block number never moves, the same header is returned
`Amount` times |
| >= 2 | `1 - Skip` underflows | walks *forward* instead of back (`Skip
= 2` on block 100 lands on 101) |

Per the `GetBlockHeadersRequest` definition, `Skip` is "Blocks to skip
between consecutive headers", so the stride is `Skip + 1` in whichever
direction the query runs. Subtracting `1 + Skip` makes the reverse
branch mirror the forward one.

The existing table test covers forward + `Skip: 1` and reverse + `Skip:
0` (which works by accident, since `1 - 0 == 1`). Added the missing
reverse + `Skip: 1` case; it fails on master:

```
--- FAIL: TestChainGetHeaders/3
    Test: TestChainGetHeaders/3
FAIL	github.com/ethereum/go-ethereum/cmd/devp2p/internal/ethtest
```

and passes with the fix (4/4).

No caller sends a reverse request with `Skip > 0` today, so nothing is
broken in the current suite. The helper computes the expected headers
that responses are checked against, though, so the moment a reverse+skip
case is added it would silently assert the wrong headers rather than
fail loudly.
2026-07-17 18:51:45 +02:00
Sina M
06b23b4293
.github: rm s1na from CODEOWNERS (#35365)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
🫡
2026-07-15 17:48:03 +02:00
Felix Lange
bde64d702d
.mailmap: consolidate healthykim committer names (#35366) 2026-07-15 17:47:45 +02:00
Bosul Mun
d91b71fb36
core/txpool/blobpool, eth: implement sparse blobpool (#34047)
This is the implementation of EIP-8070 Sparse Blobpool. It introduces
protocol version eth/72 which relays blob transaction cells instead of
full blobs.

The blobpool now store 'incomplete' transactions, where only some of
the cells are provided. The stored cell indexes are taken from the
custody bitmap, which is provided by the consensus layer in
forkchoiceUpdatedV4. This method will be called once Glamsterdam
activates, and the default custody is full custody, so for now there
is no change in the amount of stored cells for now.

The main entities added are the BlobBuffer and BlobFetcher, which work
together to track and fetch missing cells from connected peers. The
partial transactions become available for inclusion in blocks when
they are covered by enough peers that hold all cells.

This change also introduces engine_getBlobsV4, which allows for
cell-based responses (and partial blobs with only some of the cells).
We maintain backward compatibility with getBlobsV3 which expects full
blob responses by recovering the blob from available cells. Since this
process is resource-intensive, we proactively cache the conversion so
it is ready in time for getBlobsV3 calls. This mechanism will be
removed once support for getBlobsV4 is universal across all consensus
layer implementations.

devp2p tests for eth/72 are not part of this initial change. This is
to avoid breaking test success status for execution clients that do
not have eth/72 implemented yet. The tests will be added in a
subsequent change.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-07-15 14:41:04 +02:00
Sina M
c3f2851872
cmd/utils: tune GOGC for large cache values (#34851)
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
---------

Co-authored-by: jonny rhea <5555162+jrhea@users.noreply.github.com>
2026-07-14 13:00:47 -05:00
Jonny Rhea
d5d936d76c
eth/catalyst: handle bogota fork in payloadVersion (#35355)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Docker Image (push) Waiting to run
#34057 added the Bogota fork, but didn't add it to payloadVersion.
This PR fixes the CI error.
2026-07-14 17:24:07 +02:00
ozpool
3155d3ad14
core/rawdb: drop stray %d verb from freezer metadata log message (#35351) 2026-07-14 09:56:22 -05:00
cui
6e6fcef0ba
eth/protocols/eth: discard message before size check (#35289)
- Move `msg.Discard` defer ahead of the max message size check in
`handleMessage`.
- Ensures oversized messages are released when the handler returns
early.
2026-07-14 09:06:57 -05:00
Chase Wright
8d84e5001a
p2p/dnsdisc, cmd/devp2p: keep invalid and unreachable nodes out of DNS trees (#35312)
The DNS discovery crawler (ethereum/discv4-crawl) builds signed enrtree
lists by crawling the network and running the collected records through
`devp2p nodeset filter` and `devp2p dns sign`. Those records come from
external nodes, and `enr.Record` keeps entries it can't decode as raw
RLP, so a self-signed record with an out-of-range port (EIP-778 defines
ports only as "big endian integer", not `uint16`) can round-trip
verbatim into a signed tree. Consumers that decode ports strictly then
fail to decode that record.

Two publish-side checks:

- `MakeTree` rejects a record if a present port entry
(`tcp`/`tcp6`/`udp`/`udp6`/`quic`/`quic6`) does not decode as a
`uint16`. This is an invariant at the signing boundary: geth won't sign
a tree containing a record with an undecodable port, regardless of how
the node list was produced. Absent and zero ports are unaffected.

- `devp2p nodeset filter -dialable` keeps only nodes advertising a
usable RLPx port (non-zero `tcp`/`tcp6`/`quic`/`quic6`), letting the
crawler drop discovery-only and unreachable nodes so consumers aren't
handed peers they can't connect to.

The two are deliberately separate: the `MakeTree` check is a correctness
guard that always applies, while `-dialable` is an opt-in selection
filter for the crawler pipeline. A follow-up will add `-dialable` to
discv4-crawl's `filter_list`.
2026-07-14 09:05:02 -05:00
jwasinger
a10969f650
accounts/abi: fix abigen v1 bindings for deployment of library dependencies (#32164)
When we are deploying library dependencies, if the `TransactOpts` nonce
is unset we will choose the nonce of the next deployment transaction
based on the pending nonce of the sender. If a previous library
deployment transaction was made but not yet accepted into the pool, the
pending nonce will not be updated for the the next deployment
transaction.

This PR introduces a new method to the bind API `WaitAccepted` which
poll until a submitted transaction hash is accepted into the pool or
rejected. The bindings for v1 are updated to invoke this method after
deploying each library dependency.
2026-07-14 14:45:16 +02:00
lightclient
0d1cf34ec6
all: add bogota fork to config (#34057)
Adds stubs for Bogota fork.
2026-07-14 14:37:29 +02:00
rjl493456442
1ef0ffb98c
core: implement EIP-2780 and EIP-8037 changes (#35318)
Implement the spec changes of EIP-2780 and EIP-8037.

See the spec diffs in
- https://github.com/ethereum/EIPs/pull/11844
- https://github.com/ethereum/EIPs/pull/11891
- https://github.com/ethereum/EIPs/pull/11906
-
a4801f3bb1

---------

Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
2026-07-14 14:28:26 +02:00
danceratopz
abfb2de574
eth/catalyst, eth/ethconfig, cmd: make engine API max reorg depth configurable (#35335)
Some checks are pending
/ Windows Build (push) Waiting to run
/ 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
2026-07-14 15:48:30 +08:00
Marius van der Wijden
68f711b9de
beacon/engine: correct rlp encoding/decoding (#35348)
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
Correctly passes BAL around in engine api

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-07-13 15:31:10 +02:00
Marius van der Wijden
f9382c2d1b
eth/tracers/logger: respect logging limit (#35349)
Necessary for building fuzzers that don't take 10s of seconds for
tracing a test
2026-07-13 19:51:38 +08:00
cui
3140668d49
miner: cap configured MaxBlobsPerBlock to protocol limit (#35295)
## Summary

- Only apply user-configured `MaxBlobsPerBlock` when it is strictly
below the protocol-defined maximum.
- Prevents the miner from building blocks that exceed the consensus blob
limit.

## Test plan

- [x] `go test -short ./miner/`
2026-07-13 12:13:15 +02:00
cui
df7b89603c
internal/testlog: clone attributes before appending (#35324)
WithAttrs and terminalFormat appended to h.attrs directly, which can
mutate the shared slice when it has spare capacity. Clone attrs first to
avoid corrupting parent handler state.
2026-07-13 11:06:26 +02:00
cui
13bcbf0eef
core/rawdb: fix off-by-one in freezer init progress log (#35344)
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-07-13 15:56:00 +08:00
Stefan
b34a925e9e
beacon/engine, eth/catalyst: return block access lists in payload bodies v2 (#35347) 2026-07-13 15:55:39 +08:00
Marius van der Wijden
e7314c8a13
core: charge floorDataGas if it exceeds regularGas (#35342)
Implement EIP spec change
https://github.com/ethereum/EIPs/pull/11908/changes

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-07-13 09:38:54 +08:00
Marius van der Wijden
0e2cbebbd1
params: update contract addresses (#35341)
As per https://notes.ethereum.org/@ethpandaops/glamsterdam-devnet-7
2026-07-13 09:11:12 +08:00
Marius van der Wijden
3ab52d837d
go.mod: update ckzg (#35336)
Some checks failed
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Linux Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
Updates ckzg to the newest version
2026-07-10 11:42:16 +02:00
Csaba Kiraly
111e7b8b48
eth: protect high-value peers from random dropping based on tx inclusion stats (#34702)
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
The peer dropper periodically disconnects random peers to create churn.
This was previously blind to peer quality.
This PR adds peer-score based peer protection, handling the
multi-dimensionality problem of peer scoring through the concept of
protected peer pools.

---------

Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
Co-authored-by: healthykim <bsbs8645@snu.ac.kr>
2026-07-09 18:54:27 +02:00
Marius Kjærstad
5a39aa10ad
build: upgrade -dlgo version to Go 1.25.12 (#35317)
New security fix:
https://groups.google.com/g/golang-announce/c/OrmQE_Yp5Sc
2026-07-09 09:50:42 -05:00
spencer
2ce0200762
cmd/evm, core: fixes for eels tests@v20.0.0 release (#35283)
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
## Summary

Sanity fixes surfaced by running the EELS `tests@v20.0.0` fixture
release (63,109 blockchain tests) through `evm blocktest`.

Also bumps CI to consume the new release: `build/checksums.txt` now
points at `tests@v20.0.0` / `fixtures.tar.gz` from
`ethereum/execution-specs` (supersedes the archived EEST repo's
`fixtures_develop`).

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-07-09 16:27:34 +08:00
cui
896a4ab7c6
core/vm/runtime: cap regular gas budget at MaxTxGas for Amsterdam (#35301)
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-07-09 12:21:15 +08:00
cui
6c80ee6c50
eth/protocols/snap: fix access list sync progress double counting (#35323) 2026-07-09 10:52:28 +08:00
rjl493456442
76e3dc6b5b
core: improve chain reset head (#35252)
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 does a few things:

- reject `debug_setHead` if the target is even before the pivot block
(if non-nil)
- reject `debug_setHead` if in path mode, the target is not recoverable
- decouple the chain rewinding and state recovery in path mode and
recover the state in one shot

---------

Co-authored-by: jonny rhea <5555162+jrhea@users.noreply.github.com>
2026-07-08 16:44:34 -05:00
ozpool
2133e014ae
internal/ethapi: reject gasPrice together with authorizationList (#35320)
Closes #35314.

### Problem

`TransactionArgs.ToTransaction` selects `SetCodeTxType` when an
`authorizationList` is present, but then unconditionally downgrades to
`LegacyTxType` when `gasPrice` is set:

```go
case args.AuthorizationList != nil || defaultType == types.SetCodeTxType:
    usedType = types.SetCodeTxType
...
if args.GasPrice != nil {
    usedType = types.LegacyTxType
}
```

A legacy transaction cannot carry an EIP-7702 authorization list, so the
list is silently dropped. `eth_sendTransaction`, `eth_signTransaction`
and `eth_fillTransaction` can then return a plain legacy
transaction/hash even though the requested delegation update or
revocation was never included.

The downgrade also masks a latent issue: `setFeeDefaults` returns early
once `gasPrice` is set (without `authorizationList`) and never fills
`MaxFeePerGas`/`MaxPriorityFeePerGas`. Building the `SetCodeTx` without
the downgrade would hit
`uint256.MustFromBig((*big.Int)(args.MaxFeePerGas))` with a nil fee cap
and panic. Erroring early is therefore the correct behavior.

### Fix

Reject the `gasPrice` + `authorizationList` combination in
`setFeeDefaults`, mirroring the existing `gasPrice` / EIP-1559 guard, so
the request fails explicitly instead of producing a transaction that
omits the authorization list.

### Test

Added a `setFeeDefaults` case asserting the new error. Verified
fail-on-main: with the guard reverted the test fails (`expected error:
both gasPrice and authorizationList specified`); with the guard it
passes. Full `internal/ethapi` package, `go vet` and `gofmt` are clean.

### Note

The same silent-drop applies to `gasPrice` + `blobVersionedHashes` (blob
transactions also cannot be legacy). I scoped this PR to the reported
`authorizationList` case; happy to extend the guard to blob hashes in
the same spot if preferred.
2026-07-08 11:57:31 -06:00
rjl493456442
0c88fee429
eth/downloader, eth/protocols/snap: snap v2 catchup failure (#35321)
Fixes https://github.com/ethereum/go-ethereum/issues/35319
2026-07-08 10:47:39 -05:00
rjl493456442
4d2181aa41
cmd, core, eth, miner: apply 7997 in block building (#35285)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
This PR applies the 7997 irregular state transition in t8n, block
building, simulation and tracing.
2026-07-07 14:40:25 +02:00
rjl493456442
cf35a1b6f6
core/vm: add access cost check (#35261)
This is an edge case found by @weiihann. 

Under 8038, the cold storage access cost is increased to 3,000 gas,
which exceeds the sentry check threshold. Therefore, the sentry check no
longer guarantees that the remaining gas is sufficient to cover a cold
slot access.

Therefore, an additional access affordability check is added to
eliminate the potential DoS vector.
2026-07-07 14:38:08 +02:00
cui
e5c5e1897d
core/txpool/locals: nil journal writer before checking close error (#35300)
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 clears `journal.writer` immediately after `Close()` in `rotate` and `setupWriter`,
before checking the error. This prevents leaving a stale file handle that could be reused
if close fails.

---------

Co-authored-by: Bosul Mun <bsbs8645@snu.ac.kr>
2026-07-06 16:10:25 +02:00
Richard Creighton
a8a7116395
cmd/evm: respect --fuzz=false (#34975)
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
Passing `--fuzz=false` currently still selects blocktest fuzz output
mode because the command checks whether the flag was set.

This switches the blocktest fuzz-mode checks to use the boolean flag
value, so explicit false keeps the normal output path while `--fuzz`
still enables fuzz-oriented reporting.
2026-07-06 12:36:29 +02:00
cui
69d88aee93
eth/tracers: include log index in erc7562 tracer output (#35200)
Populate the Index field on captured logs, matching callTracer
behaviour.
2026-07-06 11:31:08 +02:00
Rafael Matias
7c1959b306
rpc: add --rpc.http-body-limit flag for HTTP request body size (#35224)
The HTTP JSON-RPC server caps request bodies at a hardcoded 5 MB
(`defaultBodyLimit`), with no way to raise it. EEST bloatnet depth
benchmarks post worst-case batch requests larger than that during
fill-stateful, which the server rejects with `413 Request Entity Too
Large`.

This adds `node.Config.HTTPBodyLimit` (default 5 MB), wired through to
the HTTP/WS server config, and exposes it via `--rpc.http-body-limit`
(value in **megabytes**, default 5). Default behaviour is unchanged.
2026-07-06 11:30:32 +02:00
cui
3620a947ee
params: return AmsterdamTime from ChainConfig.Timestamp (#35293)
## Summary

- Add the missing `forks.Amsterdam` case to `ChainConfig.Timestamp`.
- Callers can now look up the Amsterdam fork activation time.

## Test plan

- [x] `go test -short ./params/`
2026-07-06 11:27:34 +02:00
Marius van der Wijden
2919267b64
core: remaining spec fixes for glamsterdam (#35279)
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 fixes five remaining differences between master and
glamsterdam-devnet-6:

- RegularCost for Auths has been increased, since 8037 increases the
WARM_ACCESS cost
- Floor is anchored to the transaction base cost, not the intrinsic cost
- Auth destinations need to be recorded in the BAL before the call is
executed
- Change the place where intrinsic gas is verified in calls to delegated
addresses
- Refund state gas directly to reservoir in outer tx frame

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-07-06 09:39:09 +08:00
rayoo
415fe376a3
p2p/enode: close sources added after FairMix shutdown (#35298)
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
`FairMix.AddSource` takes ownership of the supplied iterator, but if the
mixer has already been closed it currently returns without closing that
iterator. Close the rejected source in this shutdown path so callers
racing with `Close` do not leak iterator resources.
2026-07-05 20:21:24 +02:00
ozpool
e3b6d0c86f
cmd/devp2p: fix swapped args in private-key error message (#35193)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
This fixes an error where a failed key decode prints its arguments in
the wrong order.
2026-07-03 14:54:51 +02:00
cui
217506364d
accounts: fix missing wallet drop (#35133)
The drop helper uses sort.Search on the sorted wallet list, but the
returned index can point at the next greater wallet when the target URL
is missing. Fix this by rewriting the drop to use slices.DeleteFunc and a map.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-07-03 14:50:59 +02:00
cui
6eae868a95
p2p/discover: always increment TALKREQ drop counter on timeout (#35243)
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
Increment `dropCount` on every TALKREQ dropped due to overload timeout.
Previously the counter was only updated when the throttled warning log
was emitted.
2026-07-03 13:13:46 +02:00
rjl493456442
3006c4411b
eth/protocols/eth: fix blockAccessList empty marker (#35286)
This PR addresses an issue in the eth71 `BlockAccessListsMsg` handler,

specifically: 
- if the requested bal is not accessible in the server side, 0x80
(EmptyString) will be returned as the marker
- at the client side, old message definition
`rlp.RawList[RawBlockAccessList]` assumes all the elements are List
- the message with 0x80 (kind = string) won't be decoded correctly
- the peer will be disconnected

The message definition has been changed to `rlp.RawList[rlp.RawValue]`,
which is aligned with the one in SNAP/2 protocol.
2026-07-03 11:15:07 +02:00
cui
aa3d286f54
cmd/utils: keep metrics tag values containing '=' (#35168) 2026-07-03 14:59:28 +08:00
Stavros Vlachakis
d617f4fcdb
rpc: reject block parameter with neither number nor hash (#35271) 2026-07-03 14:31:53 +08:00
rjl493456442
3d50e3eb0e
core/types/bal: enhance the bal validation (#35281)
EIP-7928 requires that each address appears exactly once in the block
access list.

In the `BlockAccessList.Validate`, the strict `isStrictlySortedFunc` is
required to detect the duplicated accounts.
2026-07-03 14:30:56 +08:00
ozpool
7aa7806c09
cmd/devp2p: close the iterator in discv4 LookupRandom (#35206)
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
The LookupRandom RPC handler obtains a node iterator from
RandomNodes() but never closes it.

RandomNodes() returns a lookupIterator backed by a cancelable
context derived from the listener's lifetime context
(newLookupIterator -> context.WithCancel). The iterator's
Close() is what calls the cancel func, so each LookupRandom call
that never closes leaks the cancel func (and any in-flight lookup
goroutine) until the discv4 listener shuts down. When the listener
serves the RPC API (discv4 --rpc) it is long-lived, so repeated
LookupRandom calls accumulate the leak.

Close the iterator when the handler returns. This matches how the
crawler already releases the same RandomNodes() iterators
(crawl.go closes every iterator it consumes).
2026-07-02 18:20:25 +02:00
cui
f9417bb279
node: match auth-schema case insensitively (#35022) 2026-07-02 18:18:58 +02:00
cui
448515a448
accounts/external: forward blob fee cap to external signer (#35167)
SignTx populated BlobHashes and the sidecar fields (Blobs/Commitments/
Proofs) for a blob transaction but never set args.BlobFeeCap. As a
result the external (clef) signer received maxFeePerBlobGas:null and
signed a transaction inconsistent with the one passed in, silently
dropping the blob fee cap.

Set args.BlobFeeCap from tx.BlobGasFeeCap() so the signing request
faithfully reflects the input transaction. This mirrors the existing
handling of the other blob-tx fields.
2026-07-02 18:12:58 +02:00
rjl493456442
c8953d10c2
core, consensus/misc, params: implement EIP-7997 (#35223)
EIP: https://eips.ethereum.org/EIPS/eip-7997
2026-07-02 14:56:18 +02:00
cui
46b79ea078
cmd/devp2p: fix test error message formats (#35138)
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
Include the actual and expected request IDs in the devp2p test 
response failure message. This also fixes the typo in the diagnostic so
mismatched responses report a useful error.

---------

Co-authored-by: Bosul Mun <bsbs8645@snu.ac.kr>
2026-07-02 12:34:06 +02:00
cui
df51c49770
core/rawdb: fix freezer close sync error message (#35135)
Print the expected freezer close sync error before the actual value in
TestFreezerCloseSync. The assertion already compared have and want
correctly, but the failure message reported them in the wrong order.
2026-07-02 16:44:04 +08:00
cui
b4f749af11
core/types: reduce allocs in CreateBloom (#35234) 2026-07-02 16:43:42 +08:00
cui
0a47739f11
cmd/devp2p: add already used flag crawlParallelismFlag (#35031) 2026-07-02 16:40:28 +08:00
rjl493456442
dd8dd1520f
core: implement EIP-8038 (#35216)
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
Implements https://eips.ethereum.org/EIPS/eip-8038
2026-07-02 09:05:51 +08:00
cui
59e89e81e5
cmd/devp2p/internal/ethtest: fix swapped args in readAccounts error (#35247) 2026-07-01 15:06:16 -05:00
Rafael Matias
7e625dd548
cmd: add amsterdam override flag (#35213)
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
Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
2026-07-01 11:55:12 +02:00
Bosul Mun
21652ef9ef
core/txpool: add blobTxForPool migration in limbo (#35209)
This PR adds blobTxForPool migration support in limbo. Previously, there
was no conversion path from limbo entries containing types.Transaction.
Now that we have the new blobTxForPool type, this PR adds migration
logic between both types. New test code (limbo_test.go) to test this
conversion is added.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-07-01 11:12:46 +02:00
Marius van der Wijden
0fbad29b94
params: remove named hardforks from bpo schedule (#35029) 2026-07-01 16:51:05 +08:00
rjl493456442
ea242145cf
core: implement EIP-7928 spec change (#35260)
https://github.com/ethereum/EIPs/pull/11838/changes
2026-07-01 10:48:13 +02:00
m1lestones
00a773dad7
accounts/abi/abigen: add GetABI() method to abigen v2 generated bindings (#35221) 2026-07-01 15:40:46 +08:00
cui
769c8c52c5
internal/ethapi: skip transfer capture for callcode in log tracer (#35248) 2026-07-01 15:40:01 +08:00
cui
dd672c6867
eth: prealloc seen map in handleTransactions (#35237)
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-07-01 10:34:08 +08:00
cui
b6e2f13a9a
accounts/keystore: fix negative timezone sign in toISO8601 (#35245) 2026-07-01 10:33:45 +08:00
Bosul Mun
5c253e557e
core/rawdb: prevent truncateHead from returning an error for empty tables (#35258)
This PR is related to the recent bug reported in #35210.

While trying to reproduce the error, I found that when the head state is
missing (e.g. unclean shutdown), we attempt to truncate the head to the
most recent block with state across all chain freezer tables.

However, for newly added tables such as the bal table, both the head and
tail are initialized to the minimum head of the existing chain freezer
tables. As a result, the `truncateHead` fails with the “truncate below
tail” error.

This PR fixes the issue by resetting newly added empty tables with
`items` as the tail when `truncateHead(items)` is called on them.
2026-07-01 09:43:11 +08:00
cui
409aaefac1
log: clone terminal handler attrs (#35141)
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
Clone the existing terminal handler attrs before appending new attrs.
This avoids a potential attr memory overwrite when append reuses the
backing array shared with the parent handler.
2026-06-30 15:12:47 +02:00
cui
32986bf084
triedb/pathdb: prealloc node map in nodeSet.write (#35232) 2026-06-30 15:12:06 +02:00
Ignacio Hagopian
04bf045303
core/state: fix account prefetching for absent accounts (#35256)
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-06-30 09:03:12 +08:00
rjl493456442
68671a4530
core: implement EIP-8246 (#35219)
EIP: https://eips.ethereum.org/EIPS/eip-8246

Supersedes #35218
2026-06-30 08:58:43 +08:00
Chase Wright
9700b5b10e
cmd/devp2p: support dual-stack discovery listener (#35220)
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
`devp2p discv4 listen` / `discv5 listen` is the supported replacement
for the removed bootnode tool, but it bound IPv4-only and `-extaddr`
took a single address, so it couldn't run a dual-stack bootnode.

This binds the listener dual-stack (falling back to IPv4-only where IPv6
is unavailable) and lets `-extaddr` take a comma-separated IPv4/IPv6
pair. A single node can then advertise both `ip` and `ip6` in its ENR
over one UDP port:

```
devp2p discv4 listen --nodekey <key> --addr [::]:30301 \
  --extaddr 203.0.113.10:30301,[2001:db8::1]:30301
```

The fallback IP is only derived from the listener when no `-extaddr` is
given, so a v4- or v6-only `-extaddr` no longer leaks a loopback entry.
All addresses must share one UDP port (single socket).
2026-06-29 15:55:42 +02:00
rayoo
a0568b1dbf
cmd/geth: release account iterator in listEIP7610EligibleAccounts (#35250)
listEIP7610EligibleAccounts opens an account iterator and never releases it.
2026-06-29 15:41:33 +02:00
cui
11524ba075
core/rawdb: fix freezer metadata log field ordering (#35246) 2026-06-29 20:59:12 +08:00
rjl493456442
eccd239a29
trie: introduce UpdateBatch (#32448)
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 feature is an optimization used in the BAL, mostly for experimental
purpose.

---------

Co-authored-by: jwasinger <j-wasinger@hotmail.com>
Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
2026-06-29 11:12:34 +02:00
rjl493456442
07dd8e052f
core: implement EIP-2780 (#35212)
Implements https://eips.ethereum.org/EIPS/eip-2780

---------

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2026-06-29 11:04:30 +08:00
cui
ab134b2101
cmd/geth: release storage iterator in snapshot dump (#35222)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
## Summary

- Release the storage iterator after iterating slots in `geth snapshot
dump`, matching the existing account iterator cleanup.

## Test plan

- [x] `go build ./cmd/geth/...`
- [ ] Manual: run `geth snapshot dump` on a node with storage data and
verify output is unchanged
2026-06-26 10:10:56 +02:00
Marius van der Wijden
4387f433c9
core: implement EIP-8282: Builder Execution Requests (#35175)
Some checks are pending
/ Windows Build (push) Waiting to run
/ 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
implements
https://github.com/ethereum/EIPs/pull/11760/changes#diff-0c9428673c7c725120dae93fda8a181c38bcfb1759d45e8accaf73b14e1f35cb

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-06-25 22:12:07 +08:00
rjl493456442
a63e2f1247
eth/downloader: fix test panic (#35215)
This PR addresses the panic in tests. As the eventLoop is spun up when
the downloader was closed, the sub will be nil and make the panic
happens.

```
  goroutine 421 [running]:
  github.com/ethereum/go-ethereum/eth/downloader.(*DownloaderAPI).eventLoop(0xcb0e4d0)
      /opt/actions-runner/_work/go-ethereum/go-ethereum/eth/downloader/api.go:91 +0x127
  created by github.com/ethereum/go-ethereum/eth/downloader.NewDownloaderAPI in goroutine 352
      /opt/actions-runner/_work/go-ethereum/go-ethereum/eth/downloader/api.go:50 +0xf2
```
2026-06-25 13:10:54 +02:00
Marius van der Wijden
38678ec516
params: bump max code size as per EIP-7954 (#35217) 2026-06-25 19:09:48 +08:00
rjl493456442
12241bde26
core: add debug log and repair the missing hash and receipts (#35190)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
This PR improves the block download used by snap sync. Specifically,
blocks and their associated data (receipts and canonical hash mappings)
are now written directly to the database without checking existence.

The current implementation could fail in cases where the block header
and body were already present (has.Block returns true), but the
corresponding canonical hash mapping was missing. One possible scenario
is when a newPayload event is processed without a subsequent
forkChoiceUpdate.

It is still unclear why Geth may re-enter snap sync after Engine API
events have been processed after the sync. Anyway, bypassing the
existence is a reasonable change.

What's more, in the downloader, the presence of canonical hash is also
considered for deciding the range of blocks to be downloaded.
Specifically:

- in the full sync, the block with header and body available but
canonical hash missing will be re-inserted;
- in the snap sync, the block with header, body and receipt available
but canonical hash missing will be re-inserted;
2026-06-23 14:46:38 +08:00
rjl493456442
aec597d7b9
core/vm: implements EIP-8037 spec change (#35173)
Implements spec change https://github.com/ethereum/EIPs/pull/11807

This PR resolves the conflict between the EIP-7928 and EIP-8037.
Specifically in contract deployment, EIP-7928 requires to not resolve 
the deployed account until it's accessed, while in EIP-8037, the early 
access is required to determine if the account-creation should
be charged or not.

This PR addresses this conflict by changing the EIP-8037 a bit,
unconditionally charge the account creation in CREATE Family 
(CreateTx, Create/Create2 opcode) and refunds the associated 
gas cost if the account creation doesn't happen ultimately.

Checkout https://hackmd.io/@bFEBbZiVSAO0IURh9qzEFg/BJmFYqCeGl for more
details

What's more, now the LIFO mechanism is used for refilling the state cost
in frame revert, frame halt, state opcode refunds.
2026-06-23 14:31:24 +08:00
Ng Wei Han
73eeee65bf
trie/bintrie: use bitarray for path encoding + fix serialization issues (#34772)
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
Replace 1-byte-per-bit path encoding with bit-packed `BitArray`,
reducing DB key size by 8x

Benchmark (sparse single-leaf write, M3 Pro):
```
                           │  Before (1B/bit)  │  After (BitArray)  │
                           │      sec/op       │  sec/op   vs base  │
CollectNodesSparseWrite-11        10.50µ ± 1%   9.78µ ± 1%  -6.86%
                           │       B/op        │   B/op    vs base  │
CollectNodesSparseWrite-11       5.50Ki ± 0%   5.09Ki ± 0%  -7.38%
                           │    allocs/op      │ allocs   vs base   │
CollectNodesSparseWrite-11          67 ± 0%       58 ± 0%  -13.43%
```

---------

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-06-22 22:26:17 +02:00
jvn
023a573732
core/rawdb/eradb: support ere files in era store (#34978)
When ancient history is pruned, geth serves old block bodies and receipts
back from era files on disk. Until now that fallback only worked for .era1
files (pre-merge), so requests for post-merge blocks backed by .ere files
failed even though the data was present. This PR generalizes the era store
to open both formats.

---------

Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2026-06-22 17:00:43 +02:00
rjl493456442
7f3afa1b71
ethdb/pebble, cmd, node: add pebble v2 support (#34009)
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 adds the support of Pebble v2, details as below:

- Pebble V2 will be used if database is empty
- Pebble V1 will be used if database is not empty and the format is old
- Upgrade command (geth db pebble-upgrade) is provided to upgrade the
format to v2 offline
2026-06-22 12:50:49 +02:00
rayoo
c80681ca73
p2p/discover: return errNoUDPEndpoint in RequestENR (#34933)
Mirror the guard applied to (*UDPv4).Dial in #34916: when the target
node has no usable UDP endpoint, return errNoUDPEndpoint instead of
silently sending the ENRRequest to an invalid AddrPort and waiting for a
timeout.

The other UDPEndpoint-using request paths in this file already do this:

  ping        v4_udp.go:215   errNoUDPEndpoint
  Ping        v4_udp.go:228   errNoUDPEndpoint
  newLookup   v4_udp.go:309   errNoUDPEndpoint
  RequestENR  v4_udp.go:358   addr, _ := n.UDPEndpoint()  <-- outlier

RequestENR is reachable from external callers like cmd/devp2p/crawl.go,
which feeds in arbitrary nodes that may not have a UDP port set. Before
this change, such nodes burn one full RPC timeout; after it, the caller
gets a clean error immediately.

The added test fails on master with "RPC timeout" and the trace logs
"PING/v4 addr=invalid AddrPort", confirming packets are being written to
an unspecified address; with the fix it returns errNoUDPEndpoint without
doing any I/O.
2026-06-22 10:48:03 +02:00
rjl493456442
b72371887a
core/vm: inline the gas deduction (#35203)
This PR inlines the gas deduction by getting rid of the tracer and use
`chargeRegularOnly` for the non-state opcode.

It fixes a performance regression introduced by EIP-8037 PR.

```

throughput MGas/s | 184.4 (±0.3%) | 193.1 (±1.0%) | +4.7% ▲
-- | -- | -- | --
mean newPayload | 164.2 ms (±0.3%) | 156.9 ms (±1.0%) | -4.5% ▲
p50 newPayload | 154.6 ms (±0.1%) | 147.6 ms (±0.7%) | -4.5% ▲
p95 newPayload | 273.3 ms (±2.3%) | 261.6 ms (±2.4%) | -4.3% ≈ noise
p99 newPayload | 403.6 ms (±4.4%) | 380.9 ms (±4.0%) | -5.6% ≈ noise

```
2026-06-22 16:33:56 +08:00
Bosul Mun
eea629b9b3
core/txpool: drop support for v0 blob sidecar (#35191)
This PR drops support for v0 blob sidecar in blobpool. Since the
osaka fork activation time has passed, these code paths are
now unused. It is assumed that only v1 transactions exist in
the blobpool.
2026-06-22 10:31:51 +02:00
Felix Lange
af7bf37b53 version: begin v1.17.5 release cycle 2026-06-22 09:47:26 +02:00
Felix Lange
36a7dc72e9 version: release go-ethereum v1.17.4 2026-06-22 09:46:12 +02:00
ozpool
6b72f26ed3
triedb/pathdb: log the expected version in obsolete-index cleanup (#35194)
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-06-22 09:59:59 +08:00
cui
e5ff3596db
p2p/discover: fix waiting wrong duration (#35002)
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
The timer should wait the remaining time, not the elapsed time.
2026-06-21 01:15:26 +02:00
Marius van der Wijden
7c9032dff6
all: change reflect.Ptr to reflect.Pointer (#35176)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
Since go 1.18 reflect has `reflect.Pointer` which replaces
`reflect.Ptr`. Newer versions of `govet` will alert. 
See also: https://pkg.go.dev/reflect#pkg-constants
2026-06-18 18:34:34 +02:00
Chase Wright
8c540cb082
eth/catalyst: add testing_commitBlockV1 (#34995)
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
Adds `testing_commitBlockV1`. It is the write companion of `testing_buildBlockV1`:
it builds a block from the provided payload attributes and transactions on
top of the current canonical head, inserts it, and sets it as the new
head, returning the new head hash.

---------

Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
2026-06-17 18:03:11 +02:00
rjl493456442
7122ecc3eb
eth/protocols/snap: remove uncovered states before resuming (#35159)
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 fixes an issue where flat states are continuously persisted
during downloadState, while the sync journal is only persisted at the
end of Sync.

As a result, an unclean shutdown can leave the on-disk flat state ahead
of the journal markers. Some persisted entries may be stale (storage
slots that should have been deleted), and these dangling entries are not
detected or fixed by subsequent state downloads.

To address this, this PR introduces a cleanup step before state
downloading begins. It removes all state entries that are not covered by
the persisted journal markers.
2026-06-17 13:44:12 +08:00
rjl493456442
0e810e4984
eth, triedb, internal: add snap/2 sync progress (#35178)
This PR does two things:

- Expose snap/2 specific sync progress fields
- Seed the sync progress after `loadSyncStatus `
2026-06-17 13:43:51 +08:00
rjl493456442
1be5da2330
eth/protocols/snap: redo the snap sync if the bal is unavailable (#35181)
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 introduces a new condition that if the local node falls behind
too much and the required BAL for catching up is very likely to be
unavailable, the entire snap sync will be restarting from scratch.

As the defined BAL retention window is weak-subjective-period which is
calculated dynamically. A more conservative threshold is used (90K
blocks) for robustness.

Apart from that, the BAL catchup will be divided into several spans and
apply one by one. It's essential to prevent the potential out-of-memory
panic of placing the entire BAL set in memory.
2026-06-17 09:57:08 +08:00
rjl493456442
ad68ce261b
eth: reserve peer slot for usable snap peer (#35180)
This PR improves the slot reservation logic in the context of snap/2.

Geth has the mechanism to reserve roughly half the peer slots for peers 
supporting the snap protocol if snap syncing is needed by local node.

With the context of snap/2, this mechanism should be changed that:
we reserve the slot for the "usable snap peer", not blindly for peer
with snap extension enabled (such as legacy snap/1, which can't serve
the snap/2).
2026-06-17 09:55:36 +08:00
cui
cb387c9bc3
cmd/devp2p/internal/ethtest: validate received txs, not the sent ones (#35170)
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
sendInvalidTxs's *eth.TransactionsPacket case iterated `txs` — the
locally-sent invalid transactions, every one of which is in `invalids`
by construction — instead of the transactions actually carried by the
received packet. As a result the loop returned "received bad tx" on the
very first TransactionsPacket the peer sent, regardless of its contents,
and never inspected what was really propagated.

Iterate msg.Items() (the decoded contents of the received packet) so the
"node must not propagate invalid txs" conformance check tests the real
condition instead of producing a false negative.

---------

Co-authored-by: Bosul Mun <bsbs8645@snu.ac.kr>
2026-06-16 15:31:02 +02:00
Jonny Rhea
6e62cc5aa8
core/vm: compute stack operations in place (#35156)
The stack primitives pop by value: pop() returns the 32-byte value
itself, so every popped operand is copied out of the stack arena before
it is used. The result side was already in place, peek returns a pointer
and binary ops write into the new stack top. This PR fixes the operand
side: pointer-returning primitives (popPtr, popPtrPeek, etc), with the
handlers rewritten to read operands directly from their arena slots.
Every popped operand paid the copy, whatever the op went on to do with
it, so this optimization covers the arithmetic and comparison ops as
much as JUMP, MSTORE, SSTORE and RETURN.

The copy is visible in the assembly. On arm64, master's opLt spends four
instructions moving the popped value through the frame, and the
comparison then reads it back from there:

LDP (R5), (R6, R7) ; load words 0 and 1 of the popped value from the
arena
    LDP  16(R5), (R5, R8)            ; load words 2 and 3
STP (R6, R7), vm.~r0-64(SP) ; store words 0 and 1 into a frame slot
    STP  (R5, R8), vm.~r0-48(SP)     ; store words 2 and 3

With popPtrPeek those four instructions are gone, the frame shrinks from
locals=0x58 to locals=0x18, and the function from 336 to 288 bytes. The
compiler cannot remove the copy itself: uint256.Int is a four-element
array, and Go's SSA does not promote arrays longer than one element to
registers, so a by-value pop pays this round trip no matter how far
inlining gets, for LT exactly as for ADD.

The CALL and CREATE families are deliberately not converted: a child
frame reuses the same stack arena, so parent pointers into popped slots
die when the child pushes. The rule is recorded on the primitives:
pointers stay valid until the next push or any sub call. Converting the
call family safely means materializing scalars before the child call,
left for later work with a call-heavy benchmark to justify it.

### Benchmarks

Measured with the benchmark suite from #35144 (the evm-bench contract
workloads and the block import benchmark), which is not part of this
PR's diff. Apple M4 Max, fixed iteration counts, n=10, all p=0.000. B/op
and allocs/op are statistically identical on every benchmark:

| benchmark | master | PR | vs master |
|---|---|---|---|
| Snailtracer | 60.0 ms | 54.1 ms | -9.8% |
| TenThousandHashes | 13.2 ms | 12.2 ms | -7.8% |
| ERC20Transfer | 11.7 ms | 11.0 ms | -5.5% |
| ERC20Mint | 7.49 ms | 7.02 ms | -6.2% |
| ERC20ApprovalTransfer | 8.92 ms | 8.44 ms | -5.4% |

This PR is independent of #35144 but plays nicely with it: the generated
dispatch there splices these handler bodies, so the in-place forms land
in its fast path too, where they measure larger.

### Testing

The rewritten handlers run on the interpreter's only execution path, so
correctness rests on references outside the change:

- **Consensus fixtures.** The full tests package passes: state tests,
the execution-spec families, blockchain tests.
- **Opcode testcases.** The JSON testcases compare individual opcode
results against committed expected values.
- **Tracer fixtures.** The tracetest reference files pin exact log and
return data shapes, covering the rewritten LOG and RETURN paths.
- **Cross-build differential.** A goevmlab campaign running this
branch's evm against master's evm over generated state tests across four
forks (Prague, Cancun, London, Osaka) with full trace comparison:
160,566 tests, zero divergences.

---------

Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
2026-06-16 07:47:05 -05:00
Jonny Rhea
a326298f51
rpc: fix flaky TestTracingHTTPTimeout (#35172)
`TestTracingHTTPTimeout` still flakes in CI after #35101, failing at the
POST:

    --- FAIL: TestTracingHTTPTimeout (0.26s)
        tracing_test.go:633: request: Post "http://127.0.0.1:43497": EOF

The test sets a short server `WriteTimeout` and posts a blocking call.
`ContextRequestTimeout` leaves a fixed 100ms for the server to write its
timeout response before the HTTP write deadline cuts the connection.

I can't repro it locally, but my theory is that under load that write
can miss the window, so the connection is dropped and the client POST
returns `EOF`, failing the test before it inspects the span. This is the
only test exposed to it because it is the only one that configures a
`WriteTimeout`.

The EOF is benign: the server sets the timeout error on the SERVER span
before attempting the write, independent of whether the client receives
the response. Since that span status is all the test asserts,
`tryPostJSONRPC` tolerates the transport error instead of failing on it.
2026-06-16 07:46:34 -05:00
rjl493456442
7d74166d3d
core: re-enable the legacy snapshot after sync (#35163)
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-06-16 11:09:32 +08:00
rjl493456442
6ed112aee0
eth/protocols/snap: fix catchup stall (#35158)
This PR fixes an issue that when peers legitimately lack a requested
BAL, empty (0x80) is delivered and this BAL entry will be refetched 
over and over again. 

A `refused` tracker is added and catchUp will fail if this BAL is
unavailable against the entire peerset.
2026-06-16 09:11:15 +08:00
Jonny Rhea
e2164cc78c
eth/downloader, eth/protocols/snap: freeze pivot once state is downloaded (#35155)
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-06-15 16:09:41 +08:00
cui
23483010a4
cmd/geth: fix logging line count error (#35136)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
2026-06-12 23:09:54 +02:00
cui
116314baf9
core/vm: fix test error message (#35134)
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-06-12 19:38:45 +02:00
Marius van der Wijden
9059157eba
core: implement EIP-8037, state creation gas cost increase (#33601)
Implements https://eips.ethereum.org/EIPS/eip-8037
mainly done in order to judge the complexity of the EIP 
and to act as a jumping off point, since the eip will likely
change.

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-06-12 14:29:03 +02:00
Sina M
d93dda49c8
internal/memlimit: respect cgroup memory cap (#34947)
Currently geth ignores the docker `--memory` directive and doesn't
adjust its cache size downward when necessary, potentially running into
OOM.

while gopsutil has functions like `docker/CgroupMem()` they are rather
for reading cgroup memory limit of a container from the host.
2026-06-12 13:31:15 +02:00
Sahil Sojitra
906727089b
p2p/discover: optimize findnodeByID (#33348)
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 adds an optimization to the `findNodeByID` function in
`p2p/discover`. There is already an open PR (#33205) for similar
improvements, and I have further optimized the function to get better
performance. I have attached the benchmark results comparing the current
`main` branch with my `optimized version`, and the results show clear
improvements.

---------

Co-authored-by: Csaba Kiraly <csaba.kiraly@gmail.com>
2026-06-12 09:10:34 +02:00
Bosul Mun
e595aedcd0
core/txpool/blobpool: add cache for GetBlobs request (#35124)
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 introduces a cache for GetBlobs request.

The main purpose of this PR is to reduce the getBlobs latency by reading and
decoding blobs from the pool in advance of the actual query. This is important
especially in the context of a sparse blobpool, since it may be necessary to
recover blobs from cells on a getBlobs request.

Previously, the Engine API read and decoded blobs from the pool on every call.
Now those calls check the cache and only fall back to the pool on a miss.

The cache has two modes:

- In topK mode (default), it wakes up periodically, picks the most profitable
  pending blob transactions up to the current fork's maxBlobsPerBlock, and loads
  their blobs. The selection logic is shared with the miner's block-building
  logic. The selection size is derived from eip4844.MaxBlobsPerBlock at the
  current head.
- When the CL calls HasBlobs, the cache switches to hasBlobs mode and tries to
  pin the set it just reported as available. Cache updates (read, decode, and
  optionally conversion in the future) run in background goroutines.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-06-11 17:26:15 +02:00
Jonny Rhea
17aab1ac9a
core, eth/protocols/snap, eth/downloader: snap/2 sync logic (#34626)
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
Adds snap/2 (EIP-8189), a block-access-list (BAL) based state sync, and
wires it to run side by side with snap/1. It's opt-in (for now) behind a
new --snap.v2 flag and chosen at startup.

https://eips.ethereum.org/EIPS/eip-8189

---------

Co-authored-by: Toni Wahrstätter <info@toniwahrstaetter.com>
Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-06-11 14:45:07 +08:00
cui
eea6242742
log: share mutex in log handles with same writer and other fields (#35074)
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
In old code, mu is struct not pointer, it caused create new mutex event
with same writer. Change to use pointer to sync.Mutex, so that the mutex
is shared between handler with same writer.
2026-06-10 22:37:39 +02:00
Felix Lange
8a8becaeab
beacon/engine: ensure nil ExecutionPayloadEnvelope.BlockValue doesn't crash (#35140)
Found while updating to go-ethereum master in prysm.
2026-06-10 20:03:13 +02:00
Felix Lange
e444c267a2
rpc: add option to configure TextMapPropagator on client (#35132)
This adds a client option to configure trace context propagation via the
`traceparent` HTTP header.
I'm adding this so that prysm can enable distributed tracing on their
engine API client.
2026-06-10 12:04:54 -05:00
Guillaume Ballet
39b17c5585
all: fix all typos, as reported by crates-ci/typos (#35008)
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 is a PR that removes all correctly flagged typos, in order to stop
an onslaught of slop PRs in its tracks. It should be followed by #34994
but the latter needs more configuration work and I want to limit the
stem of PRs right now.
2026-06-10 18:50:51 +02:00
cui
11f0a8318b
node: fix wrong status code in ws (#35111)
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 an issue where we would falsely return 400 when we should return
200 because the request was served successfully

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-06-10 08:30:52 +02:00
Guillaume Ballet
43b7b4e8d9
eth: fix borked test introduced in merging #33347 (#35130)
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 a lint issue introduced via #33347.
2026-06-09 18:13:24 +02:00
cui
08aaa7c5ff
eth: add debug_clearTxpool api (#33347)
Implement a similar RPC as what reth offers https://github.com/paradigmxyz/reth/pull/18539, to clear the tx pool.
2026-06-09 14:39:46 +02:00
cui
10614fc423
beacon/engine: only print the bad hash on error (#35112)
Better error messages on the engine api
2026-06-09 08:15:49 -04:00
rayoo
1f87331fbc
eth/protocols/eth: track announced tx hashes only after send (#35122)
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
Co-authored-by: jwasinger <j-wasinger@hotmail.com>
2026-06-08 16:02:20 -04:00
cui
e774a8fca0
cmd/utils: validates trimmed string but parses the untrimmed one (#35116) 2026-06-08 13:25:32 -05:00
cui
31d227ea83
cmd/devp2p: swap want and got (#35125) 2026-06-08 12:06:16 -05:00
cui
0ee70187fd
accounts/abi, core, metrics, miner, rlp, signer, triedb: fix all incorrect variable usages in error strings (#35121)
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 is trying to stem further slop PRs by going over all incorrect
strings and fixing them.

---------

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-06-08 12:39:10 +02:00
cui
f1b2573dda
accounts/abi: array-parse error reports the wrong character (#35106) 2026-06-08 12:00:30 +02:00
rjl493456442
13d8df63f4
core/types/bal: improve the bal validation (#35110)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
cb1364d60e
2026-06-05 10:44:41 +08:00
Jonathan Oppenheimer
bc1967f088
core/state/snapshot: snapshot generation shutdown race condition (#33540)
## Overview

This PR fixes a race condition during blockchain shutdown where snapshot
generation could continue accessing the trie database after it has been
closed, leading to iterator errors. We noticed this in one of our nodes
on https://github.com/ava-labs/avalanchego, which relies on an older
version of geth with the same issue (so this behavior does happen!).

During node shutdown, the following sequence occurs:

1. `BlockChain.Stop()` calls `snaps.Release()` to clean up snapshot
resources
2. `Release()` only resets the cache but doesn't stop the generator
goroutine
3. The trie database is then closed via `triedb.Close()`
4. The still-running generator attempts to iterate storage tries
5. Iterator fails because the database is closed (`"Generator failed to
iterate storage trie"`)

## Problem

There are three related bugs:

1. `Release()` doesn't stop generation: The `diskLayer.Release()` method
only resets the cache without stopping ongoing snapshot generation,
leaving the generator goroutine running after database closure.
2. `stopGeneration()` has an incorrect completion check: The
`stopGeneration()` method checks `genMarker != nil` to determine if
generation is running. However, `genMarker` is set to nil when
generation completes successfully, even though the generator goroutine
is still waiting for the abort signal at the end of `generate()`. See
line 705 in `generate.go`:
eaaa5b716d/core/state/snapshot/generate.go (L699-L707)
This means `stopGeneration()` returns early without sending the abort
signal.
3. Node shutdown doesn't stop generation: During shutdown, no code path
calls `stopGeneration()` or sends the abort signal to the generator,
causing the generator to access a closed database and error.

## Fix

- Modified `diskLayer.Release()` to call `stopGeneration()` before
releasing resources
- Added cancelation architecture, removing reliance on someone having to
wait
- Fixed `stopGeneration()` to properly and safely stop snapshot
generation
- Added `TestGenerateGoroutineLeak` to verify the fix and prevent
regression. The test fails without the fix and passes with it.
- The test creates a snapshot with active generation, waits for
completion, then calls `Release()`, and uses `go.uber.org/goleak` to
assert no generator goroutine survives.
- Without the fix, the test fails: `Release()` returns without stopping
the generator, which stays parked at `generate.go:705` waiting for an
abort signal that never comes:

    ```
    --- FAIL: TestGenerateGoroutineLeak (0.88s)
        generate_test.go: found unexpected goroutines:
        [Goroutine 6 in state chan receive, with
         core/state/snapshot.(*diskLayer).generate on top of the stack:
         core/state/snapshot.(*diskLayer).generate(...)
            core/state/snapshot/generate.go:705
         created by core/state/snapshot.generateSnapshot
            core/state/snapshot/generate.go:79 ]
    ```
- With the fix, the test passes: `Release()` -> `stopGeneration()`
blocks until the generator goroutine has fully exited, so nothing leaks

Note that this fix follows the same pattern used in `Tree.Disable()` in
https://github.com/ethereum/go-ethereum/pull/30040, which introduced
`stopGeneration()` for use in `Disable()` and `Rebuild()` but didn't
address the shutdown path.

The test follows the same pattern used in
`TestCheckSimBackendGoroutineLeak`
2026-06-04 21:22:58 -05:00
cui
f5c62d0552
core/types: BlobHashes should iterate Commitments (#35109)
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
Previously was iterating Blobs, but that could cause panic if the sidecar is malformed.
2026-06-04 11:17:46 -06:00
ozpool
dcf6d0c135
rpc: accept Windows reset error in websocket read limit test (#34928)
### Summary

`TestServerWebsocketReadLimit/limit_with_large_request_-_should_fail` is
flaky on `windows/amd64` (see [run
25364841576](https://github.com/ethereum/go-ethereum/actions/runs/25364841576/job/74378334589)
referenced in #34877):

```
--- FAIL: TestServerWebsocketReadLimit/limit_with_large_request_-_should_fail (0.02s)
    server_test.go:279: unexpected error for read limit violation: read tcp 127.0.0.1:56703->127.0.0.1:56700:
        wsarecv: An existing connection was forcibly closed by the remote host.
```

When the server enforces the read limit and tears the connection down,
the client's read can race the close frame. On Windows the OS surfaces
that race as `wsarecv: An existing connection was forcibly closed by the
remote host` instead of the gorilla `CloseError(1009)`,
`websocket.ErrReadLimit`, or the POSIX `connection reset by peer` the
test already tolerates.

This change adds `"forcibly closed"` to the set of acceptable error
substrings for the failure case, so the Windows reset is recognized as a
valid signal that the server enforced the limit.

### Fixes

#34877

### Test plan

- [x] `go test -count=5 -run TestServerWebsocketReadLimit ./rpc/`
(darwin/arm64) — pass
- [x] `go test ./rpc/...` — pass
- [x] `go vet ./rpc/...` / `gofmt -l rpc/server_test.go` — clean
- [ ] CI on `windows/amd64` confirms the flake no longer trips

---------

Co-authored-by: lightclient <lightclient@protonmail.com>
2026-06-04 10:57:11 -06:00
cui
7835a71dae
core/types: fix length of BlobVersionedHashed can not be zero (#35065)
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
check the len of BlobVersionedHashed in blob tx.
2026-06-03 15:51:27 -06:00
Yorick Downe
369521becb
cmd/utils: avoid extra newlines when reading era checksums (#35104)
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
The checksum count during EraE import is off by one when `checksums.txt`
ends its last line on a newline, as the pandaops file does. The current
code would result in one empty string after the final `\n`, something
like

```
[]string{
    "line1",
    "line2",
    "line3",
    "",
}
```

Trim off the final `\n`, if it exists: `return
strings.Split(strings.TrimRight(string(b), "\n"), "\n"), nil`

---------

Co-authored-by: lightclient <lightclient@protonmail.com>
2026-06-03 11:48:45 -06:00
Guillaume Ballet
f493364590
build, cmd/geth, signer: remove clef (#35097)
`clef` is a great tool, however:

 * It is no longer maintained
 * No one else in the team can pronounce it properly

We are however receiving some slop PRs for it, so I think it's time -
with infinite sadness - to say goodbye.
2026-06-03 16:39:12 +02:00
Sina M
eb429a062a
core/txpool: drop reorged v0 blob sidecars (#35099)
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
With Osaka being a while ago I believe we can drop this transition and
drop the tx instead.
2026-06-03 21:26:18 +08:00
Chase Wright
6b451a4245
internal/ethapi: default block parameter to latest on state methods (#35100)
Make the `Block` parameter optional on the six state-reading methods,
defaulting to `latest` when omitted:

- `eth_getBalance`
- `eth_getCode`
- `eth_getStorageAt`
- `eth_getTransactionCount`
- `eth_getProof`
- `eth_getStorageValues`

This implements the behavior proposed in https://github.com/ethereum/execution-apis/pull/812.

---------

Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com>
2026-06-03 12:35:12 +02:00
Sina M
80d9ba5d97
internal/era: update to latest ere spec (#34896)
Update the EraE (ere) reader and builder to the latest e2store ere spec
  (https://github.com/eth-clients/e2store-format-specs/pull/16).

  The reader now derives the component layout from the on-disk e2store type
  tags via the dynamic block index, rather than assuming fixed slot positions.
  This makes the optional components (receipts, td, proof) resolvable in any
  supported subset.

---------

Co-authored-by: lightclient <lightclient@protonmail.com>
2026-06-03 11:52:10 +02:00
Jonny Rhea
f4393173f2
triedb: reconcile stale storage roots in GenerateTrie, add cancel support (#34807)
Rewrites triedb.GenerateTrie as a single partitioned pass that
reconciles stale account.Root fields and rebuilds the trie at the same
time, with 16-way parallelism and crash resume baked in.

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-06-03 15:08:09 +08:00
Jonny Rhea
e514ede494
rpc: fix flaky otel tests (#35101)
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
The response can reach the client before the deferred spanEnd fires, so
call `httpsrv.Close()` before GetSpans is called.
2026-06-02 12:50:57 -05:00
cui
38667bc64e
p2p/nat: server list contains IPv6 servers (#35084)
stun-list.txt includes 10 bracketd IPv6 server, but the dial network is
fixed to "udp4"
2026-06-02 17:13:36 +02:00
Jonny Rhea
19f5fe079b
rpc, internal/telemetry: trace JSON-RPC response writes (#35049)
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
The per-call SERVER span ended inside `handleCall()`, so the JSON-RPC
response write happened after the span closed. For large responses like
`engine_getBlobsV*`, that write time was missing from traces.

- Extend the SERVER span past `writeJSON`. 
- For batches, add a top-level `jsonrpc.batch` SERVER span (with `rpc.batch.size`) covering the whole batch including `callBuffer.write`.
- Add `rpc.writeJSON` span around the non-batch response write.
- Add `rpc.writeJSONBatch` span around the batch response write.
- Add `rpc.httpWrite` span around the actual HTTP write, separating JSON encoding from network write.
- Add additional telemetry helpers.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-06-02 14:13:06 +02:00
rjl493456442
77a2816468
eth/protocols/snap: introduce snapv2 skeleton (#35098)
This PR is a prerequisite for landing snap v2, the BAL-healing snap sync
algorithm.

It duplicates much of the snap v1 skeleton, which is expected to be
deprecated once v2 is enabled. The code duplication is acceptable as a 
short-term tradeoff, simplifying development and reducing integration 
complexity.
2026-06-02 14:48:26 +08:00
rjl493456442
02dd66dfc0
core/txpool/locals: fix data race (#35096)
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
Supersedes #35060

```
go test -race ./core/txpool/locals/
ok      github.com/ethereum/go-ethereum/core/txpool/locals      1.782s
```
2026-06-02 09:46:11 +08:00
rjl493456442
fdf99d9883
core/rawdb, ethdb, cmd, triedb: manage finalized block-accessList in freezer (#34977)
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 implements flat-file storage for finalized block access lists,
specifically:

* The freezer is extended with the notion of tail groups, allowing
different groups within a single freezer instance to maintain
independent tails, while all tables within the same group remain
tail-aligned.

* The freezer can now dynamically attach new tables to an existing
freezer instance, with both the table head and tail initialized to the
freezer's common head.

* A new freezer table, **bals**, has been added to the chain freezer
with its own dedicated tail group, preserving the flexibility to deploy
a tail-pruning policy different from the main chain data group.

Additionally, the BALs in the key-value store will be migrated to the
freezer instance once they are finalized or there are at least 90K block
confirmations on top acting as a "soft finalization". This freezing
policy is same with all chain segment data.
2026-06-01 11:01:42 +08:00
cui
00f7c72ca7
core/txpool/blobpool: blob pool with status queue (#35075) 2026-06-01 10:57:13 +08:00
cui
831ef5a453
node: only delete db ref on close successfully (#35083) 2026-06-01 10:56:38 +08:00
cui
5016e54406
eth/protocols/eth: only track after send is okay (#35086) 2026-06-01 10:56:23 +08:00
cui
ff45d1dd7b
internal: SetCodeTx tx.To must not be nil (#35094) 2026-06-01 10:56:05 +08:00
Marius van der Wijden
b71f750916
core, core/txpool, eth: move subscriptions to constructor (#35048)
Closes https://github.com/ethereum/go-ethereum/issues/20554
It makes it easier to reason about the lifecycle.
2026-06-01 08:13:59 +08:00
Jonny Rhea
046a10e8a7
go.mod: bump go.opentelemetry.io from 1.40.0 to 1.41.0 (#35073)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
#35016 + cmd/keeper go mod tidy
2026-05-29 22:51:26 +02:00
cui
33711da476
accounts/abi: fix wrong want count for events (#35077) 2026-05-29 22:27:11 +02:00
Felix Lange
b908022511
rpc: always set content-length on HTTP responses (#35072)
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
We recently changed the JSON encoding logic to use an internal `[]byte`
buffer.
This means we can now always set `Content-Length` on the response.
2026-05-29 08:20:01 -05:00
Richard Creighton
7a73ffe8a3
accounts/usbwallet: check ledger versions for typed txs (#35044)
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
Checks the Ledger Ethereum app version before sending typed transactions
that require newer app support.

EIP-2930/EIP-1559 transactions now require Ledger app v1.9.0 or newer,
and EIP-7702 transactions require v1.17.0 or newer. Older apps now
return the same kind of local update error already used for earlier
Ledger feature gates instead of sending an unsupported transaction to
the device.

---------

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-05-29 08:11:42 +02:00
Nikhil
0ef867b292
triedb/pathdb: fix swapped want/got args in journal-root mismatch error (#35067)
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-05-29 08:38:04 +08:00
Guillaume Ballet
61342e9c01
trie/bintrie: record inserted leaves for t8n (#34843)
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
Because the UBT doesn't differentiate slots from accounts, the content
of the tree can not be exported as a `GenesisAlloc`, which means that
`evm t8n` can not intergrate it. We have tried integrating the new
format into execution-specs, but this is very hard to maintain because
the team doesn't see it as a priority and their own repository is seeing
a lot of churn. This PR adds the ability to capture the structure of
what is being inserted in the tree, so that the information isn't lost
and it can be dumped in the t8n context.

---------

Co-authored-by: felipe <fselmo2@gmail.com>
2026-05-28 17:06:47 +02:00
Barnabas Busa
95320ffe69
miner: set slot number for pending block post-Amsterdam (#34792)
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-05-28 10:52:27 +02:00
rayoo
4017efe345
rpc: reject empty batch in BatchCallContext (#34985)
The server already rejects empty batches with -32600. On the client
side, calling BatchCallContext with a zero-length slice on inproc/WS/IPC
transports registers no request IDs but the server still replies with an
error message whose id is null. The dispatch loop has no requestOp to
match it to, so op.resp is never written and op.wait blocks until ctx
deadline.

Short-circuit on len(b) == 0 with the same invalidRequestError the
server uses, so all transports return immediately with -32600.
2026-05-28 10:38:34 +02:00
Marius van der Wijden
9f434c04db
go.mod: update pion/dtls (#35062)
Updates dtls to newest version
2026-05-28 10:16:15 +02:00
cui
10a1982203
eth/protocols/eth: fix track-before-send (#35056)
Track the transaction only after it was sent out
2026-05-28 10:05:40 +02:00
Jonny Rhea
b0df33967c
node, cmd/clef, graphql: disable gzip on engine API (#35057)
Add a disableGzip parameter to NewHTTPHandlerStack and httpConfig.
initAuth sets it true so compression is disabled in the engine api.
Public HTTP RPC behavior is unchanged.
2026-05-28 09:30:08 +02:00
cui
ab20d50dba
log: return TerminalHandler write errors from Handle (#35055)
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
Propagate slog Handle failures when the underlying io.Writer rejects
output.
2026-05-27 12:27:35 -04:00
cui
f4a90d178a
rpc: fix method-name matched before maxMethodNameLength (#35038)
Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
2026-05-27 16:32:51 +02:00
cui
9d21f6ebd5
crypto/ecies: correctly return ErrInvalidMessage (#35037) 2026-05-27 16:30:03 +02:00
Guillaume Ballet
14820029c9
cmd/clef, cmd/geth: remove CLI flags that were deprecated for more than a year (#35021)
This is another one of my slop-PRs, aimed at reducing the amount of
future slop PRs by doing it all in one go.

All of the deprecated cli flags have been in that state for over a year.
It's time to remove them, especially since they are ineffective.

Note that I kept the code to report and manage deprecated cli flags, as
I assume we will be deprecating more flags in the future.
2026-05-27 14:58:31 +02:00
ozpool
45698e9cb9
p2p/nat: bump pion/stun to v3 to pull in fixed pion/dtls (#34980)
### Summary

Closes #34621.

`github.com/pion/dtls/v2` is affected by
[CVE-2026-26014](https://nvd.nist.gov/vuln/detail/CVE-2026-26014); the
fix lives in `github.com/pion/dtls/v3`. In this tree, dtls/v2 is pulled
in indirectly via `github.com/pion/stun/v2 v2.0.0` (declared at
`go.mod:53`), which is the only direct consumer — `p2p/nat/stun.go` is
the sole call site.

`github.com/pion/stun/v3` already uses dtls/v3, so bumping `stun`
upgrades the vulnerable dependency without touching `pion/dtls`
directly.

### API check

The v3 surface used by `p2p/nat/stun.go` is byte-identical in shape to
v2:

| Symbol | v2 | v3 |
|---|---|---|
| `Dial` | `func Dial(network, address string) (*Client, error)` | same
|
| `Build` | `func Build(setters ...Setter) (*Message, error)` | same |
| `TransactionID` | `var TransactionID Setter` | same |
| `BindingRequest` | `var BindingRequest = NewType(MethodBinding,
ClassRequest)` | same |
| `Event` | `type Event struct` | same |
| `XORMappedAddress` | `type XORMappedAddress struct { …
GetFrom(*Message) error }` | same |
| `DefaultPort` | `const DefaultPort = 3478` | same |

So the code change is just the import rename plus an alias rename to
keep the local label honest (`stunV2` → `stunV3`).

### Change

`go.mod` / `go.sum`:

- Replace direct `github.com/pion/stun/v2 v2.0.0` with
`github.com/pion/stun/v3 v3.0.1`.
- `go mod tidy` drops every `pion/dtls/v2` and `pion/stun/v2` entry from
`go.sum` and pulls `pion/dtls/v3 v3.0.7`, `pion/stun/v3 v3.0.1`,
`pion/transport/v3 v3.0.8` as the new indirect set.

`p2p/nat/stun.go`:

- Update the import path and rename the alias from `stunV2` to `stunV3`.

### Verification

- `go build ./p2p/nat/` clean.
- `go test ./p2p/nat/ -count=1` passes (26s).
- `grep 'pion/dtls/v2\|pion/stun/v2' go.sum` returns zero matches.

### Notes

- `pion/dtls` is not imported directly anywhere in the tree, so no other
code needs touching.
- `pion/transport/v3` was already in the dependency graph (the `stun/v3`
upgrade just bumps the patch from v3.0.1 → v3.0.8); the v2 transport
drops out cleanly.
2026-05-27 13:38:18 +02:00
lightclient
1a2333650a
eth/catalyst: import new payload if at genesis, regardless of sync status (#32673)
fixes #32672

This is kind of a band aid solution since it fixes the issue by
bypassing the snap sync expectations of an empty db and attempting to
import the new payload if we're at block 1. The next FCU will set the
status to synced.

Will continue looking to better understand how the above issue arises
and find a more thorough solution.

---------

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2026-05-27 12:57:13 +02:00
Minh Vu
c782197d48
graphql: limit request body size (#35034)
Fixes #35033

## Problem

The GraphQL HTTP handler decoded request bodies directly before
executing the query. Unlike the JSON-RPC HTTP path, `/graphql` did not
have an explicit request body limit before JSON decoding.

A single `Decode` also stops after the first JSON value, so the handler
now requires EOF after the GraphQL request object to ensure oversized
trailing request data is not ignored.

## Changes

- Limit GraphQL request bodies to 5 MiB, matching the existing JSON-RPC
default body limit.
- Return `413 Request Entity Too Large` when the limit is exceeded.
- Require EOF after the request JSON object.
- Add regression coverage for oversized query bodies and oversized
trailing request data.
- Fix an existing GraphQL test fixture that had an unintended trailing
quote after the JSON object.

## Validation

- `gofmt -w graphql/service.go graphql/graphql_test.go`
- `go run golang.org/x/tools/cmd/goimports@latest -w graphql/service.go
graphql/graphql_test.go`
- `go test ./graphql -run TestGraphQLHTTPBodyLimit -count=1`
- `go test ./graphql -count=1`
2026-05-27 12:53:34 +02:00
cui
90cd7d1937
eth: should return basefee for the next block as doc says (#35023) 2026-05-27 12:53:03 +02:00
locoholy
ac1fdc5f8f
internal/ethapi: add eth_capabilities RPC method (#33886)
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
There is currently no way for JSON-RPC clients to discover which
historical data a node can serve without probing with trial-and-error
calls and interpreting opaque error messages (`pruned history
unavailable`).

This makes it hard to build robust tooling on top of nodes that prune
their history, for example nodes started with `--history.chain
postmerge`
or with reduced `TransactionHistory`, `LogHistory`, or `StateHistory`
windows.

This PR implements `eth_capabilities` as defined in
ethereum/execution-apis#755. The method takes no parameters and returns
the current head plus six per-resource capability records:
- `state`
- `tx`
- `logs`
- `receipts`
- `blocks`
- `stateproofs`

Closes #33828
2026-05-27 10:15:09 +02:00
vickkkkkyy
ace9c51233
cmd/utils: fix archive mode detection for TransactionHistory override (#33880)
Archive nodes store the full history of transactions in the index. This PR
fixes a bug for users who provided the NoPruning field in a YAML config file.
Now geth correctly stores full transaction history if archive is configured via
YAML.

---------

Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2026-05-27 09:03:32 +02:00
Sina M
d902837256
core/vm: global cache for jumpdest bitmaps (#34850)
```
● Global JUMPDEST Cache - engine_newPayload benchmark
  ============================================================
  Commit before: a06558042 (master)
  Commit after:  faef2454f (core/vm: global cache for jumpdest bitmaps)
  Blocks: 1k mainnet (24950066 → 24951065)
  Runs: 3 each, clean ZFS clone per run

                  Before (avg)    With Falcon (avg)   Δ
  Throughput      176.0 MGas/s    190.7 MGas/s        +8.3%
  Mean NP         172.3ms         159.0ms             -7.7%
  p50             162.8ms         150.7ms             -7.4%
  p95             282.4ms         259.8ms             -8.0%
  p99             391.0ms         371.6ms             -5.0%

  Machine: Intel Ultra 7 255H, 62GB DDR5, NVMe (ZFS), governor=performance, turbo=off
  ```

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-05-27 09:01:05 +02:00
cui
622cef2d06
eth/protocols/snap: fix error message (#34976)
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-05-26 20:45:14 +08:00
Sina M
5933fa4bbf
.github: cancel CI run for stale PR commits (#34964)
Each commit on a PR kicks off a CI run. Those CI jobs run to the finish
regardless, even when new commits have been pushed which make them stale
and useless. This change attempts to cancel any previously running job
for the same PR.
2026-05-26 14:44:56 +02:00
Richard Creighton
cae4c5f93c
cmd/utils: respect --state.size-tracking=false (#35011)
Passing `--state.size-tracking=false` currently cannot disable state
size tracking when it was enabled by the config file because the CLI
path only turns the config value on.

---------

Co-authored-by: Jared Wasinger <j-wasinger@hotmail.com>
2026-05-26 20:44:40 +08:00
cui
c6b2a27f85
graphql: end == 0 and begin > 0 should be reject (#35032) 2026-05-26 14:21:07 +02:00
cui
9429725d2d
p2p/discover: waitForNodes hangs on RespCount=0 from peer (#35043)
The first NODES response sets total = min(int(response.RespCount),
totalNodesResponseLimit), With RespCount=0, total=0 but receive become
1; receive == count is never satisfied.
2026-05-26 14:18:47 +02:00
cui
ca1a027fae
core: add slot number (#35036) 2026-05-26 12:27:07 +02:00
cui
8209b9cb05
accounts/abi: forEachUnpack ABI error message arguments swapped (#35046)
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-05-26 10:29:00 +02:00
Sina M
c0fc5e0bda
internal/ethapi: fix base fee too low error code in eth_simulateV1 (#34951)
Fixes the issue discovered in
https://github.com/NethermindEth/nethermind/issues/11412.
2026-05-26 09:36:28 +02:00
Richard Creighton
d3edc58ef7
graphql: handle missing block body in Raw resolver (#35027)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
Return empty raw bytes when the GraphQL `Block.raw` resolver cannot load
the block body. This matches the nil handling used by the other
block-body-backed resolvers and avoids exposing RLP empty-list bytes as
raw block data.
2026-05-22 13:59:02 +08:00
rayoo
a059a357d1
eth/catalyst: count actually-available blobs in getBlobs (#35028) 2026-05-22 13:58:31 +08:00
felipe
12eabbd76d
cmd/evm/internal/t8ntool: Amsterdam t8n updates; adds BAL and slotNum (#35025)
The changes here enable us to fill tests with Amsterdam using geth EVM
bin.

This will be useful for block builder tests using `testing_buildBlockV1`
endpoint and for filling benchmarking compute and stateful tests as
Python is too slow for benchmark tests.

Tested in
[ethereum/execution-specs](https://github.com/ethereum/execution-specs)
with:

```
uv run fill --clean --fork=Amsterdam tests/amsterdam/eip7928_block_level_access_lists/test_block_access_lists.py --evm-bin=$GETH_EVM_PATH
```
2026-05-22 11:40:09 +08:00
Miki Noir
92cd26cae0
core: add code cache hit/miss meters (#34821) 2026-05-22 11:33:21 +08:00
Jonny Rhea
2522b716f4
eth/catalyst, core/txpool/blobpool: add tracing to GetBlobs endpoints (#35026)
- Adds tracing to the `GetBlobsV1/V2/V3`
- Adds `blobs.requested` and `blobs.filled` attributes to
`GetBlobsV1/V2/V3` spans.
- Adds tracing to `BlobTxPool().GetBlobs()`
2026-05-22 11:24:14 +08:00
Ignacio Hagopian
4daaaadfc4
eth/catalyst: implement engine_newPayloadWithWitnessV5 and use witness field spec ordering (#35009)
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:
- Adds `engine_newPayloadWithWitnessV5`. The codebase already supports
the previous `VX`, so only `V5` was missing.
- Make the consensus witness format use the field [ordering defined in
the
spec](8d7e68f4b7/src/ethereum/forks/amsterdam/stateless_host_exec_witness.py (L175-L176))
to make it canonical.

cc @gballet

---------

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-05-21 21:00:57 +02:00
DeFi Junkie
36520d8199
accounts/usbwallet: add support for blob and setcode transactions (#33797)
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
Adds Ledger signing support for BlobTxType (EIP-4844) and SetCodeTxType
(EIP-7702) transactions.

---------

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-05-21 15:31:26 +02:00
Minh Vu
dc07433d87
beacon/engine: preserve nil blob list JSON (#35019)
Fixes a regression where nil results from getBlobs were encoded as an empty array instead of null.


---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-05-21 09:56:15 +02:00
Marius van der Wijden
ef5041ef4d
eth/catalyst: engine_hasBlobs (#34859)
Co-authored-by: healthykim <bsbs8645@snu.ac.kr>
Co-authored-by: Felix Lange <fjl@twurst.com>
2026-05-21 09:54:32 +02:00
Jonny Rhea
efe58eac00
beacon/engine, rpc: optimize JSON encoding for large blob payloads (#33969)
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
Adds a fast path for ExecutionPayloadEnvelope and BlobAndProofListV*
that bypasses encoding/json's reflection and re-validation, which are
expensive for large payloads with many blobs. Also hand-rolls the
jsonrpcMessage wire encoding in the RPC codec to avoid a second
re-validation pass when writing responses to the connection.

Resolves #33814

---------

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
Co-authored-by: Felix Lange <fjl@twurst.com>
2026-05-20 20:25:56 +02:00
rjl493456442
918d46b942
core, cmd, internal: rework BAL json marshalling to adhere EELS (#34972)
Some checks are pending
/ 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
/ Linux Build (push) Waiting to run
It's a change to BAL json marshalling and t8n tooling to adhere the EELS
definition.
2026-05-20 09:12:13 -04:00
jwasinger
50ae34c1d8
core/types/bal: add additional static validation for access lists (#34967)
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
Updates the static validation logic to cover additional edge cases
(reflecting the state of the latest devnet branch, except cleaned up
slightly).

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-05-20 09:35:28 +08:00
Bosul Mun
a484a8506d
eth/protocols/eth: implement eth71 bal response (#34879)
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 implements the serving side of the eth71 BAL exchange messages.
Until commit 4cd7092 also contained the requesting side, but since that
part still needs more work, I'm splitting it out into a separate PR.

The test injects BALs directly into rawdb. This can be removed once BAL 
generation is integrated into the chain maker.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-05-19 20:25:13 +02:00
rjl493456442
1bdc4a60d9
core, consensus, internal, eth, miner: construct block accessList (#34957)
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 finally lands EIP-7928, collecting the block accessList during
the block execution and verifying against the block header.

---------

Co-authored-by: jwasinger <j-wasinger@hotmail.com>
Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2026-05-19 21:51:53 +08:00
cui
e3ce773b8c
internal/ethapi: propagate SetHead errors to API (#35001)
Return blockchain rewind failures from debug_setHead instead of ignoring
them.
2026-05-19 15:22:03 +02:00
cui
970e3cd6f0
beacon/light: fix lock after lock deadlock (#34800) 2026-05-19 12:33:09 +02:00
cui
4f4bfdbea7
beacon/light/sync: check error (#34818) 2026-05-19 12:21:43 +02:00
William Morriss
1149f76dca
internal/ethapi: add eth_baseFee RPC method (#34904)
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 method is similar to `eth_blobBaseFee` but returns the next base
fee.
2026-05-19 08:05:00 +02:00
cui
3d1e6aa6c3
signer/core: fix unconditional http request metadata scheme overwrite (#34653)
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-05-18 16:30:41 +02:00
Andrii Furmanets
d4027f3d46
node: normalize HTTP vhost host matching (#34693)
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-05-18 10:37:12 +08:00
cui
8a0223e8da
core/txpool: use blobTxForPool inside of Reset function (#34960)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
This PR fixes a bug in the current blobpool `Reset` function where it
used the Transaction type instead of blobTxForPool.

Decoding transactions fetched from the pool as Transaction type 
caused an error because the blobpool stores blobTxForPool types.
2026-05-15 15:51:46 +02:00
Sina M
6f6d006f74
core/txpool/blobpool: silence GetRLP miss-log spam (#34965)
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
Avoids every legacy tx hash query hitting the blob pool on the path of
BlobPool.GetRLP.
2026-05-15 18:04:37 +08:00
cui
31bb680997
miner: re-use basefee and big.Int in loop (#34783)
Some checks are pending
/ Windows Build (push) Waiting to run
/ 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
2026-05-14 13:45:49 +02:00
Barnabas Busa
da34eb59fd
node: default OpenTelemetry SampleRatio to 1.0 (#34948)
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
## Summary

The `--rpc.telemetry.sample-ratio` flag declares `Value: 1.0` and `geth
--help` advertises `(default: 1)`. In practice, however, omitting the
flag produces a sample ratio of `0`, causing
`sdktrace.TraceIDRatioBased(0)` to drop 100% of spans. Users who enable
`--rpc.telemetry` see the `OpenTelemetry trace export enabled` log line
and a clean startup, but no traces ever leave the process.

The root cause is the interaction between two pieces of code:

1. `cmd/utils/flags.go:setOpenTelemetry` (added in #34062) only copies
the flag value when `ctx.IsSet(...)` returns true:

   ```go
   if ctx.IsSet(RPCTelemetrySampleRatioFlag.Name) {
       tcfg.SampleRatio = ctx.Float64(RPCTelemetrySampleRatioFlag.Name)
   }
   ```

That is the right pattern for "don't clobber a config-file value with
the CLI default," but it implies that something else must initialise the
field when neither source sets it.

2. `node/defaults.go:DefaultConfig` never initialises
`OpenTelemetry.SampleRatio`, leaving it at the float64 zero value.

The result for the common CLI-only user (no TOML config) is `SampleRatio
= 0` → every span is silently dropped, despite the documented default of
1.

## Change

Seed `OpenTelemetry: OpenTelemetryConfig{SampleRatio: 1.0}` in
`node.DefaultConfig` so the documented default matches runtime behavior
and the `ctx.IsSet` guard in `setOpenTelemetry` continues to do what it
was designed to do.
2026-05-13 14:08:21 -05:00
rjl493456442
b2aa6987de
core/state: track the block-level accessList (#34803)
This PR extends the journal to track the pre-transaction values of
mutated balances, nonces, and code.

At the end of the transaction, these values are used to filter out no-op
changes, such as balance transitions from a-> b->a. These changes are
excluded from the block-level access list.

Additionally, there is a dedicated `bal.ConstructionBlockAccessList`
objects for gathering the state reads and writes within the current
transaction. These state writes will be keyed by the block accessList
index.

---------

Co-authored-by: jwasinger <j-wasinger@hotmail.com>
2026-05-13 20:38:47 +08:00
rjl493456442
0494cdce23
core: introduce GasChangeHook v2 (#34946)
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 introduces OnGasChangeV2 tracing hook, as the pre-requisite for landing
EIP-8037.

---------

Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com>
2026-05-13 10:53:47 +02:00
Richard Creighton
21c5a287f9
cmd/abigen: respect --v2=false (#34943)
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
Passing `--v2=false` currently still selects the v2 binding generator
because the command checks whether the flag was set.

This switches generation to use the boolean flag value, so explicit
false continues to generate legacy bindings while `--v2` keeps selecting
v2.
2026-05-12 09:02:40 -04:00
cui
6af374e6aa
accounts/abi: fix unittest code (#34740)
1. should use !reflect.DeepEqual.
2. big.NewInt(0).SetBits([]big.Word{}) work around for DeepEqual when
big.Int is zero, unpack return a []big.Word{}.
2026-05-12 08:50:04 -04:00
cui
91f8e7cd9e
internal/ethapi: add balHash to block results (#34652) 2026-05-12 14:49:33 +02:00
Bosul Mun
726d657a4a
core/txpool/blobpool: add blobTxForPool type (#34882)
This PR introduces a separate transaction pool type for sparse blobpool.

In sparse blobpool, PooledTransactions message delivers transactions without
blobs, partial or full cells are downloaded by Cells message. Blobpool no longer
stores transactions with complete sidecars, and it stores transactions without
blobs, along with the corresponding cells. Because of this, a dedicated type
distinct from types.Transaction is required.

This PR introduces a type called `BlobTxForPool` and stores each sidecar field
independently, in order to bypass the assumption that a sidecar always exists as
a complete unit.

Reintroducing the conversion queue was considered, but was ultimately omitted
because type conversion should be sufficiently fast. With sparse blobpool, blob
-> cell computation would take about ~13ms per blob. Not sure whether this is
fast enough, but otherwise we can add the conversion queue later on the sparse
blobpool branch.
2026-05-12 13:59:33 +02:00
Lessa
ab28bda83e
eth/catalyst: fix getBlobsV3 partial/complete metrics (#34666)
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
In b2843a11d, metrics check len(res) == len(hashes) but res is
pre-allocated with make(), so length is always equal. Partial hit metric
never fires. Count non-nil elements instead.

---------

Co-authored-by: Bosul Mun <bsbs8645@snu.ac.kr>
2026-05-12 12:16:44 +02:00
cui
d446676fc4
core: write head hash to db after snap sync is complete (#34912)
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-05-12 10:05:39 +08:00
Sina M
c16684c1ee
internal/ethapi: fix withdrawal regression in eth_simulateV1 (#34939)
Fixes the regression caught by
https://hive.ethpandaops.io/#/test/generic/1778481210-e59b7465e1d04f7ed1b0200838584b16?testnumber=137.
engine.AssembleBlock explicitly expects withdrawals to be non-nil for
pre-Shanghai blocks as opposed to FinaliseAndAssemble which stripped off
the withdrawal.
2026-05-11 20:33:43 -04:00
rjl493456442
56d391b601
cmd, core, internal, miner: wrap pre/post-execution (#34812)
This is a refactoring PR to wrap all pre/post-execution system calls as
the exported functions, eliminating the duplicated system calls across
the codebase.

There are a few things unchanged but worths highlight:

- ChainMaker is left as unchanged, a significant rewrite is required
- BeaconRoot in header should be non-nil if Cancun is enabled

---------

Co-authored-by: jwasinger <j-wasinger@hotmail.com>
2026-05-11 16:17:48 -04:00
Daniel Liu
298c83502b
cmd/evm: fix gasUsed in evm run cmd (#34732)
In the --create path, execFunc returns gasLeft as the second return
value, but the rest of the code treats this value as "gas used" (printed
as such, and compared in timedExec). This makes gas reporting incorrect
and can cause benchmark consistency checks to fail.
2026-05-11 21:32:19 +02:00
rayoo
22919cec1b
eth/tracers: fix data race on interruption reason across tracers (#34827)
Every tracer that implements Stop/GetResult held a `reason error` field
that is written by Stop (called from the trace-timeout watchdog
goroutine in api.go) and read by GetResult (called by the RPC handler
main goroutine). These accesses were unsynchronized.
2026-05-11 21:21:31 +02:00
rjl493456442
8b39453122
version: start release 1.17.4 cycle (#34938)
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-05-11 23:57:06 +08:00
rjl493456442
117e067f0f
version: release go-ethereum v1.17.3 stable (#34937) 2026-05-11 17:19:24 +02:00
Marius van der Wijden
e1047b9c84
core: use uint256 in core.Message (#34934)
Changes core.Message to use Uint256 which is faster

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-05-11 22:25:57 +08:00
Richard Creighton
2f11dccca0
cmd/geth: respect --dev=false (#34920)
Passing `--dev=false` currently still enters the dev-mode startup path
because a couple of branches check whether the flag was set, not its
boolean value.

This switches those branches to use `ctx.Bool`, so explicit false does
not start dev mode or emit a dev genesis, while `--dev` keeps its
existing behavior.
2026-05-11 22:08:55 +08:00
rayoo
934a0091fa
triedb/pathdb: fix layer 5 key range in storage iterator traversal test (#34883)
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-05-11 10:23:58 +08:00
Marius van der Wijden
18becee8cb
appveyor.yml: remove appveyor configuration (#34720)
Removes the appveyor.yml since we moved to github runners.

---------

Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
Co-authored-by: Felix Lange <fjl@twurst.com>
2026-05-10 22:54:57 +02:00
rayoo
f63c265092
internal/download: close dst on io.Copy error (#34910)
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-05-10 13:43:40 +02:00
cui
7facf9c129
core/txpool: use cmp.Compare instead of subtraction (#34918)
This fixes a theoretical overflow condition if an account has an impossibly high nonce.
2026-05-10 13:03:57 +02:00
cui
bcb68d23b3
p2p: handle return false from TCPEndpoint (#34916) 2026-05-10 13:02:46 +02:00
vickkkkkyy
8581125a21
crypto: add hash length check in nocgo VerifySignature (#33839)
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
I was tracing a signature verification issue in a nocgo build and found
that `VerifySignature` doesn't validate hash length. #33104 added the
check to `Sign` and `sigToPub` but missed this one. The cgo path in
`secp256k1/secp256.go` already rejects non-32-byte hashes, so the nocgo
path should do the same — otherwise a wrong-length hash gets passed to
decred's `Verify` and silently gives a bogus result.
2026-05-10 11:49:17 +02:00
Marius Kjærstad
2ba9be9c0e
build: upgrade -dlgo version to Go 1.25.10 (#34911)
New security fix:
https://groups.google.com/g/golang-announce/c/qcCIEXso47M
2026-05-10 11:45:23 +02:00
Richard Creighton
2ca3a6447d
cmd/geth: respect --graphql=false (#34914)
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
Passing `--graphql=false` currently still registers the GraphQL handler
because the startup path checks whether the flag was set, not its
boolean value.

This switches the registration condition to use `ctx.Bool`, so explicit
false disables GraphQL while the default behavior remains unchanged.
2026-05-09 16:07:12 +02:00
cui
b927ff8b53
cmd/devp2p: fix typo in ENR IP printing code (#34909) 2026-05-09 15:59:03 +02:00
cui
1f3989dc70
signer/core: avoid mutating the input (#34908)
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-05-09 08:51:12 +08:00
Sina M
592209c0ee
.gitea, build: cross-compile windows binaries (#34889)
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-05-08 15:18:24 +02:00
Miki Noir
0ad890e3af
core/txpool/blobpool: continue on cell proof error in GetBlobs (#34891)
`GetBlobs` returned early when `CellProofsAt` reported
corrupted/out-of-bounds proofs, dropping every blob already collected
and aborting the remaining hashes — a single bad sidecar killed the
whole Engine API batch for consensus clients. Replaced the `return nil,
nil, nil, err` with `log.Error + continue` so the slot stays `nil` per
the sparse-array contract, matching the store/RLP/nil-sidecar branches a
few lines above.
2026-05-08 12:43:31 +02:00
Felix Lange
281dc4c209
p2p/discover: decouple nodeFeed from Table mutex in waitForNodes (#34898)
Fixes #34881

This fixes a hang in `Table.waitForNodes`. It is a replacement for PRs
#34890, #33665 which tried to fix the same issue in a different way.

- #34890 doesn't really fix the issue, just makes it less likely
- #33665 tries to fix it by moving the feed send outside of the lock

I created this PR because I want to keep the synchronous node feed
sending in `Table.nodeAdded`.

---------

Co-authored-by: Csaba Kiraly <csaba.kiraly@gmail.com>
2026-05-08 11:33:19 +02:00
Delweng
1abbae239d
eth,node: replace the deprecated TypeMux with Feed (#32585)
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
replace the not used event.Typemux to event.Feed

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-05-08 10:12:46 +08:00
cui
e71098ba4e
core/state: fix StateDB Reader Error Discard After Commit (#34899)
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-05-07 18:40:26 -04:00
cui
e1e3eaa381
p2p/discover: copy buffer before sending read errors to unhandled (#34888)
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 fixes an issue where packets send to the `Unhandled` channel
configured on discv4 could be corrupted when the packet buffer gets
reused.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-05-07 15:18:04 +02:00
cui
f7b7d4c7e5
eth/tracers/logger: fix exclude address list (#34887)
Fixes the exclusion list of the accessListTracer.

---------

Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com>
2026-05-07 14:03:32 +02:00
Roshan
c5598fe958
core/txpool: change lock in Pending method of legacy pool to read lock (#32924)
This PR makes a small update to the `Pending()` method in the legacy
pool. By changing the lock from exclusive to read-only, it aims to
improve concurrency performance.

---------

Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
2026-05-07 10:44:26 +02:00
Bosul Mun
ea1cf7bf5e
eth/protocols/eth: stop serving on unavailable responses (#34787)
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 is an alternative PR for
https://github.com/ethereum/go-ethereum/pull/34746.
This PR implements the second approach among the two possible solutions
mentioned in the above PR.

Requests for unavailable items are possible when the peer is following a
different fork from us. However this is not expected to happen
frequently. Considering the amount of complexity added to the codebase,
the simpler approach (this PR) can be preferred.
2026-05-06 15:36:54 +02:00
Jonny Rhea
06c30cc7e1
triedb/pathdb: add AdoptSyncedState for snap/2 completion path (#34874)
This PR adds `AdoptSyncedState()` alongside `Enable()`. It does the same
pathdb bookkeeping (now factored into a shared `resetForReactivation()`
helper), but skips the regeneration. The wiring/calling code lands in
#34626

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-05-06 21:08:15 +08:00
Rahman
b92c86deb7
internal/download: don't discard dst.Close error (#34866)
When `io.Copy` succeeds but the buffered `Close` fails (e.g. disk full
on `Flush`), the error was swallowed and verification reported a
misleading hash mismatch instead of the real I/O failure. Keep the
`Close` error when `io.Copy` didn't already produce one.

---------

Co-authored-by: Jared Wasinger <j-wasinger@hotmail.com>
2026-05-06 15:02:03 +02:00
Marius van der Wijden
aaa2b66285
core: implement eip-7981: Increase Access List Cost (#34755)
based on: https://github.com/ethereum/go-ethereum/pull/34748

spec: https://eips.ethereum.org/EIPS/eip-7981
2026-05-06 12:03:11 +02:00
Marius van der Wijden
4d2af275e1
eth/catalyst: allow reorging the head block to a parent (#34767)
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
Implements https://github.com/ethereum/execution-apis/pull/786/changes
as discussed on standup today

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-05-06 09:59:51 +02:00
cui
84949107ce
beacon/engine: fix wrong presize bound (#34860) 2026-05-06 15:18:12 +08:00
Andrii Furmanets
4ff33ba1b6
internal/download: only report stale existing downloads (#34849)
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
## Summary

Fixes #31917.

`geth era-download` now only prints `is stale` when an existing
downloaded file fails checksum verification. Missing files are still
downloaded normally, but no longer get mislabeled as stale.

## Why

`DownloadFile` used `verifyHash` for both missing files and checksum
mismatches, then printed `is stale` for any error. This made first-time
downloads look like corrupt or outdated files.

## Validation

- `make all`
- `go run ./build/ci.go test`
- `go run ./build/ci.go lint`
- `go run ./build/ci.go check_generate`
- `go run ./build/ci.go check_baddeps`

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-05-05 22:17:09 +02:00
rayoo
60db25b070
p2p/discover: restore nextTimeout update in UDPv4 resetTimeout loop (#34878)
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
The refactor from `for el := plist.Front(); ...; el = el.Next()` to the
new `iterList` iterator in #34743 silently dropped two things needed by
resetTimeout:

1. `nextTimeout = el.Value.(*replyMatcher)` at the top of the loop. This
assignment is what gives `nextTimeout` its documented meaning ("head of
plist when timeout was last reset"), and what makes the early-return
optimization at the top of resetTimeout work. Without it, nextTimeout is
only ever written to nil, so `nextTimeout == plist.Front().Value` is
always false and the optimization is dead.

2. `nextTimeout.errc <- errClockWarp` in the clock-warp branch now reads
a stale or nil pointer. Prior to the refactor, the inner assignment kept
nextTimeout pointing at the current matcher so its errc was the right
channel to receive the errClockWarp signal. After the refactor, on first
entry into the clock-warp branch nextTimeout is nil, which panics the
UDPv4 loop goroutine with a nil pointer deref and takes discv4 down.

Re-assign `nextTimeout = p` at the head of the loop (restoring the
documented invariant) and send the clock-warp error on `p.errc` rather
than the now-stale `nextTimeout.errc`.

The clock-warp branch triggers only when the system clock jumps backward
after a deadline is assigned (deadline - time.Now() >= 2*respTimeout,
i.e. at least ~500ms backward jump), which is why this regression
slipped past CI - it is not exercised by any existing unit test, and
writing one would require plumbing a clock through the loop.
2026-05-05 15:28:28 +02:00
cui
5b837e5786
eth/downloader: use batch index in deliver reconstruct (#34870)
The reconstruct callback indexes parallel response slices (bodies,
receipts). Passing the accept counter used the wrong element when an
earlier header in the same batch hit a stale slot.
2026-05-05 12:41:22 +02:00
TenderDeve
d5edb80438
accounts/abi/bind: re-export event signature errors (#34868)
Re-exports errors in bind package.
---------

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2026-05-05 11:29:26 +02:00
rayoo
efd6cdcff1
eth/tracers: forward V2 state hooks through mux tracer (#34869)
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 the muxTracer to correctly forward events to v2 state
hooks, i.e. `OnCodeChangeV2` and `OnNonceChangeV2`.
2026-05-04 21:36:26 +02:00
Rahman
f0b21fa110
core/txpool/blobpool: fix gapped queue size cap (#34831)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
the gapped queue cap was effectively per-sender rather than total — a
sender pool spread across enough distinct addresses could grow
`p.gapped` well past `maxGapped`, defeating the resource bound.

`maxGapped` was being compared against `len(p.gapped)`, which is a
`map[address][]tx` and counts unique senders, not queued txs. Switched
the check to `len(p.gappedSource)` (keyed by tx hash, so its length is
the real total). Also wired up a `blobpool/gapped/count` gauge plus
`promoted`, `evicted`, and `gappedfull` meters so queue size and churn
are actually observable in prod.
2026-05-02 13:29:21 +02:00
rayoo
7155c65abb
internal/ethapi: apply block overrides to header in eth_call (#34842)
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
Apply block overrides to header in eth_call so EIP-1559 fee fields
use the correct overridden basefee.
2026-05-01 20:32:49 +02:00
hero5512
8656efcf5b
ethclient/simulated: disable log indexing by default (#32594)
Disables the recently added log indexer from a simulated backend.
In most cases the log indexer is not required and unindexed search
should be fast enough.
Fixes https://github.com/ethereum/go-ethereum/issues/32552.
2026-05-01 20:27:57 +02:00
cui
d270e211d1
core/state/snapshot: fix condition in iterator traversal test (#34638)
Fixes a condition in a snapshot-related test.
2026-05-01 20:22:48 +02:00
Richard Creighton
41b856d472
ethclient: add maxUsedGas to simulate call results (#34820)
This updates the typed `ethclient` model for `eth_simulateV1` call
results to include `maxUsedGas`, matching the field already returned by
the server-side RPC response.

Follow-up to #32789.
2026-05-01 20:18:14 +02:00
felipe
b9c5fe6d26
eth/tracers: fix evm trace for t8n (#34862)
The mux tracer fanned out every standard hook to its children but never
forwarded OnSystemCall{Start,End}. Tracers that rely on these - like
`logger.jsonLogger`, which uses the start hook to silence its opcode
hook for the duration of a system call - never got the signal when
wrapped behind a mux.

In evm t8n, combining `--trace` with `--opcode-count` (default for geth
with exec specs) produces exactly that wrapping. The first system call
(e.g. `ProcessBeaconBlockRoot`) then fires `OnOpcode` on the json logger
before any `OnTxStart` has run, dereferencing a nil env and crashing
t8n.

Forward both hooks through the mux. The V2 fan-out falls back to V1 for
children that only implement the legacy hook, mirroring the precedence
already used in `core/state_processor.go`.
2026-05-01 16:38:33 +02:00
Guillaume Ballet
a15778c52f
trie: group 2^N binary trie nodes in serialization (#34794)
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 addresses one of the biggest performance issue with binary
tries: storing each internal node individually bloats the index, the
disk, and triggers a lot of write amplifications. To fix this issue,
this PR serializes groups of nodes together.

Because we are still looking for the ideal group size, the "depth" of
the group tree is made a parameter, but that will be removed in the
future, once the perfect size is known.


This is a rebase of #33658

---------

Co-authored-by: Copilot <copilot@github.com>
2026-05-01 15:28:19 +02:00
cui
68646229a0
internal/era/onedb: return false if err (#34816)
Next() function in RawIterator returned true on decompression errors.Now it
returns false on those cases. Redundant error check on cmd/era/main.go is also
removed.

---------

Co-authored-by: Bosul Mun <bsbs8645@snu.ac.kr>
2026-05-01 14:10:41 +02:00
cui
19dc690af8
triedb/pathdb: fix layer 5 key range in account iterator traversal test (#34639)
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
The layer-5 diff condition used `i > 50 || i < 85`, which is true for
almost all keys in the 0..255 loop. Use `i > 50 && i < 85` so layer 5
only covers the intended band (51..84), consistent with the snapshot
iterator test fix.
2026-05-01 00:24:22 +08:00
Bosul Mun
75a64ee341
eth/downloader: drop peers sending invalid bodies or receipts (#34745)
- Fixes an error shadowing issue in the deliver() function, where a
stale result from GetDeliverySlot caused the original failure to be
overwritten by errStaleDelivery.
- Adds errInvalidBody and errInvalidReceipt to the downloader error
checks to properly drop peers who sent invalid responses.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-04-30 17:55:26 +02:00
Giulio rebuffo
01036bed83
core: skip tx gas cap after Amsterdam (#34841)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
EIP-7825 caps the transaction gas limit at `MaxTxGas`, but after
Amsterdam/EIP-8037 the transaction gas limit can include state gas
reservoir in addition to the regular gas dimension. Applying the Osaka
cap to the full `tx.Gas()` rejects otherwise valid Amsterdam
transactions that need more than `MaxTxGas` total gas because of state
gas, while their regular gas use remains within the intended limit.

This changes geth to stop applying the full transaction gas cap once
Amsterdam is active:

- txpool stateless validation no longer rejects `tx.Gas() > MaxTxGas`
under Amsterdam
- legacy pool reorg cleanup does not purge high-total-gas transactions
at the Osaka transition if Amsterdam is also active
- execution precheck mirrors the txpool behavior and does not reject
high-total-gas messages under Amsterdam

The block gas limit check remains in place, so transactions still cannot
request more total gas than the current block gas limit.

Validation run:

```
go test ./core/txpool ./core/txpool/legacypool
go test ./core -run TestStateProcessorErrors
```

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-04-28 17:25:16 +02:00
Miki Noir
db8d6abced
accounts/keystore: enable fsnotify watcher on linux/arm64 (#34834) 2026-04-28 15:36:01 +02:00
cui
0c0d299c52
core/state: opt stateObject.GetState (#34825) 2026-04-28 20:33:40 +08:00
rjl493456442
b5d9c8d1c2
core: implement BAL reader for prefetching (#33737)
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-04-28 13:10:15 +02:00
Guillaume Ballet
4dc7d46155
core/vm: implement stack arena (#33960)
Here, we change the EVM stack implementation to use an 'arena', i.e.
a shared allocation pool for sub-call stacks. The stack is now more
GC-friendly, since it is a slice of uint256 values instead of a slice of pointers.

Code that pushes an item to the stack has been changed to get() the top
item, then overwrite it.

The PR is a rewrite/rebase of #30362.

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2026-04-28 11:10:44 +02:00
Rahman
51c97216c5
p2p/discover: fix timeout loop early exit when removing expired matchers (#34743)
Save `el.Next()` before calling `plist.Remove(el)` so iteration
continues correctly. Previously the loop exited after removing the first
expired matcher because `Remove` invalidates the element's links.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-04-28 10:57:58 +02:00
cui
822e7c6486
accounts/scwallet: truncate before write (#34815)
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
Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-04-27 16:13:42 +02:00
felipe
442bd28b0b
cmd/evm/internal/t8ntool: stream t8n alloc to ease heavy memory cases (#34785) 2026-04-27 20:35:49 +08:00
Rahman
a065580422
triedb/pathdb: compute size in StateSetWithOrigin.decode (#34828)
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
`StateSetWithOrigin.decode()` was missing size computation after
deserializing origin data, causing `size` to remain zero after journal
reload. Added the same calculation logic used in
`NewStateSetWithOrigin()`.
2026-04-27 15:25:57 +08:00
rjl493456442
2d5da60371
core/types/bal: update the BAL definition to the latest spec (#34799)
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 updates the BAL structure definition to the latest the spec,

- Balance has been changed from [16]byte to uint256
- Storage key and value has been changed from [32]byte to uint256 
- BlockAccessList has been changed from a struct to a slice of
AccountChanges
- TxIndex has been changed from uint16 to uint32
2026-04-26 23:32:39 +08:00
cui
b26391773d
core/state: and instead of or (#34819)
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-04-26 11:54:07 +02:00
rayoo
b70d9a4b8e
core/state,core/types/bal: copy stateReadList in StateDB.Copy
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
The stateReadList field introduced by #34776 to track the state access
footprint for EIP-7928 was not propagated by StateDB.Copy. Every other
per-transaction field that lives alongside it (accessList,
transientStorage, journal, witness, accessEvents) is copied explicitly,
so this field was simply missed.

After Copy the copy's stateReadList is nil while the original keeps its
entries, so the nil-safe guards on StateAccessList.AddAccount / AddState
silently drop every access recorded on the copy. For any post-Amsterdam
code path that copies a prepared state and keeps reading from the copy,
the BAL footprint becomes incomplete.

Add a Copy method on bal.StateAccessList and invoke it from
StateDB.Copy, matching the pattern used for accessList and accessEvents.

---------

Co-authored-by: jwasinger <j-wasinger@hotmail.com>
2026-04-24 17:30:03 +02:00
rayoo
8091994e7b
eth/protocols/snap: fix data race on testPeer counters (#34802)
The testPeer request counters (nAccountRequests, nStorageRequests,
nBytecodeRequests, nTrienodeRequests) were plain int fields incremented
with ++. These increments happen in Request* methods that are invoked
concurrently by the Syncer from multiple goroutines
(assignBytecodeTasks, assignStorageTasks, etc.), causing a data race
reliably detected by go test -race.

Change the counters to atomic.Int64 so increments and reads are
synchronized without introducing a mutex.

Fixes races detected in TestMultiSyncManyUseless,
TestMultiSyncManyUselessWithLowTimeout,
TestMultiSyncManyUnresponsive, TestSyncWithStorageAndOneCappedPeer,
TestSyncWithStorageAndCorruptPeer, and
TestSyncWithStorageAndNonProvingPeer.
2026-04-24 13:37:34 +02:00
Bosul Mun
0da22dee45
eth/fetcher: lazy-allocate hashes slice in scheduleFetches
scheduleFetches.func1 is the biggest allocator in the long-duration
profile of node (11% of total alloc_space).
Each peer-iteration pre-allocated make([]common.Hash, 0, maxTxRetrievals),
even for peers that end up collecting no new hashes (all their announces
were already being fetched by someone else).

Defer the slice allocation to the first append. Peers that collect zero hashes
now pay zero allocation, which is the common case on the timeoutTrigger
path where all peers with any announces are iterated.
2026-04-24 13:24:52 +02:00
Sina M
c876755839
Update eth/fetcher/tx_fetcher.go
Co-authored-by: jwasinger <j-wasinger@hotmail.com>
2026-04-24 12:12:26 +02:00
YQ
33c1bd59ff
rpc: send WebSocket close frame on client disconnect (#33909)
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
When `rpc.Client.Close()` is called, the TCP connection is torn down
without sending a WebSocket Close frame. The server sees `websocket:
close 1006 (abnormal closure): unexpected EOF` instead of a clean 1000
(normal closure).

### Root cause

`websocketCodec.close()` delegates to `jsonCodec.close()` which calls
`c.conn.Close()` — gorilla/websocket's `Conn.Close` explicitly "[closes
the underlying network connection without sending or waiting for a close
message](https://pkg.go.dev/github.com/gorilla/websocket#Conn.Close)"
(per RFC 6455).

### Fix

Send a WebSocket Close control frame (opcode 0x8, status 1000) before
closing the underlying connection. Uses `WriteControl` with the same
`encMu` mutex pattern already used by `pingLoop` for write
serialization, and reuses the existing `wsPingWriteTimeout` (5s)
constant.

`WriteControl` errors are safe to ignore — the connection may already be
broken by the time we attempt the close frame.

Fixes #30482
2026-04-24 11:27:39 +02:00
cui
6ece4cd143
crypto: fix unit test (#34811)
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-04-24 10:02:34 +08:00
Bosul Mun
526ad4f6f1
crypto/kzg4844: add cell-related functions (#34766)
Some checks are pending
/ Windows Build (push) Waiting to run
/ 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
This PR adds three cell-level kzg functions required for the sparse
blobpool (eth/72).

- VerifyCells: Verifies cells corresponding to proofs. This is used to
verify cells received from eth/72 peers.
- ComputeCells: Computes cells from blobs. This is needed because user
submissions and eth/71 transaction deliveries contain blobs, while
eth/72 peers expect cells.
- RecoverBlobs: Recovers blobs from partial cells. This is needed to
support both eth/71 and eth/72

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-04-23 15:39:07 +02:00
Sina Mahmoodi
2ca74d2ef9 eth/fetcher: lazy-allocate hashes slice in scheduleFetches
scheduleFetches.func1 is the single biggest allocator in the Pyroscope
profile of a busy node (~13.5 GB/hr, 8% of total alloc_space). Each
peer-iteration pre-allocated 'make([]common.Hash, 0, maxTxRetrievals)'
= 8 KB, even for peers that end up collecting no new hashes (all their
announces were already being fetched by someone else).

Defer the slice allocation to the first append. Peers that collect zero
hashes now pay zero allocation, which is the common case on the
timeoutTrigger path where all peers with any announces are iterated.

New benchmarks BenchmarkScheduleFetches_{100peers_10new,
100peers_allFetching, 500peers_3new} (benchstat, 6 samples):

  scenario            ns/op       B/op        allocs/op
  100p/10new          unchanged   unchanged   unchanged   (fast path)
  100p/allFetching   -62%        -92%        -20%
  500p/3new          -22%        -44%         -7%
  geomean            -33%        -65%         -9%
2026-04-23 08:38:40 +00:00
Matus Kysel
8e2107dc39
cmd/devp2p: fix disconnect decoding in rlpx ping (#34781)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Docker Image (push) Waiting to run
The rlpx ping command mishandled disconnect responses on two counts:
the error return from rlp.DecodeBytes was ignored, so decode failures
silently produced an "invalid disconnect message" error with no context;
and the decoder assumed the spec-compliant list form exclusively, while
older geth and some other implementations send the reason as a bare
byte.
                                                                  
Accept both wire forms (matching the legacy-tolerant behavior already
  in p2p.decodeDisconnectMessage), and on decode failure include the raw
payload so operators can see exactly what the peer sent. Add a unit
  test for the decoder covering both forms plus the empty-payload error
  path.
2026-04-22 16:48:38 +02:00
Sina M
b0ead5e17b
.gitea: add installer and archive steps for windows (#34793)
Adds the installer + archive steps that were done on appveyor to gitea
builder.
2026-04-22 16:18:29 +02:00
Guillaume Ballet
eb3283fb2e
accounts/usbwallet: revert github.com/karalabe/hid to fix freebsd build (#34784)
This PR reverts the last change to the freebsd build, and it fixes the
_direct_ FreeBSD build.

Here, we change the upstream of github.com/karalabe/hid to its new home,
github.com/ethereum/hid. The new dependency includes a dummy.go file
that makes `go mod vendor` work.

##### Origin of the problem

Enrique is maintaining the FreeBSD ports, and FreeBSD ports only support
vendored go modules. It turns out that `go mod vendor` will not include
C files if there is no `.go` file in the directory. Since the C files
were missing for `karalabe/hid`, the ports maintainer tried to use the
version of `hidapi` that is provided by the ports. To do so, he had to
modify the way things are included. This broke the _out of ports_
FreeBSD build.
2026-04-22 12:32:19 +02:00
Sina M
87b030780e
.github: add windows runner (#34742)
Difference to Appveyor:

- Missing 386 build. Hit some issue because user-space memory there is
around 2Gbs. Also seems generally extremely niche.
- Not doing the archive step and NSIS installer and uploads (those are
done on the builder).
2026-04-22 12:18:56 +02:00
rjl493456442
6f02965aab
core: track the state access footprint (#34776)
Some checks are pending
/ 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
/ Linux Build (push) Waiting to run
This is a pre-requisite PR for landing the BAL construction
2026-04-22 13:42:49 +08:00
cui
3abc4cea35
core/state: use address hash cache if available (#34780) 2026-04-22 11:05:59 +08:00
cui
dca3cf02a2
core: pre-allocate the receipt slice (#34786) 2026-04-22 11:02:44 +08:00
rjl493456442
d422ab39d5
consensus, core, internal, miner: remove FinalizeAndAssemble (#34726)
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 removes `FinalizeAndAssemble` from the consensus engine
interface
and relocates block assembly logic outside of the consensus engine.

Block assembly is consensus-agnostic. Most validations can be performed 
by the caller. For example:

- Withdrawals must be nil prior to Shanghai
- After Shanghai upgrade, withdrawals must be non-nil, even if empty.

The only notable consensus-specific validation is related to uncles. In
clique,
the concept of uncles does not exist, and any block containing uncles
should
be considered invalid.

Within the block production package, the policy is to produce blocks
according
to the latest chain specification. As a result, Clique-specific block
production
is no longer supported. This tradeoff is considered acceptable.
2026-04-21 20:58:21 +02:00
Guillaume Ballet
c374e74ee1
trie/bintrie: print todot path in binary (#34777)
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
The nodes were named using the byte representation of the path, instead
of the binary representation. This was confusing to other client devs
trying to achieve interop.
2026-04-21 14:50:09 +02:00
Barnabas Busa
f568ab9931
internal/telemetry: add gRPC transport for OTLP trace export (#33941)
## Summary
- Add `grpc://` and `grpcs://` URL scheme support for OTLP trace export
alongside existing `http://`/`https://`
- The OTLP spec defines two transports: HTTP (port 4318) and gRPC (port
4317). Many observability backends (Jaeger, Tempo, Datadog) prefer gRPC
for lower overhead
- Both `otlptracehttp` and `otlptracegrpc` return `*otlptrace.Exporter`,
so only exporter construction changes — everything downstream (batch
processor, tracer provider, lifecycle) is untouched
- Update flag usage strings to be transport-agnostic

## Example usage
```
geth --rpc.telemetry --rpc.telemetry.endpoint grpc://localhost:4317
geth --rpc.telemetry --rpc.telemetry.endpoint grpcs://tempo-grpc.example.com:443
```

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 14:48:21 +02:00
cui
077d83387a
metrics: reset internal value slice in Clear (#34761) 2026-04-21 13:58:49 +02:00
Marius van der Wijden
ac406c2fe7
core: implement eip-7976: Increase Calldata Floor Cost (#34748)
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
Increases calldata floor cost from 10/40 to 64/64
2026-04-21 16:20:02 +08:00
Toni Wahrstätter
e447a2696d
core/rawdb: clarify ReadLastPivotNumber comment (#34773)
clarify that `ReadLastPivotNumber` returns `nil` only when snap sync has
never been attempted, since the marker is written during snap sync and
never cleared.
2026-04-21 09:19:03 +08:00
rjl493456442
acbf699c33
core/state: export StateUpdate struct (#34724)
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
In the recent refactoring, the state commit logic has been abstracted, 
making it more flexible to design state databases for various use cases.
For example, execution-only modes where state mutation is disabled.

As part of this change, the database interface was extended with a 
Commit function. However, it currently accepts an unexported struct
`stateUpdate`, which prevents downstream projects from customizing
the state commit behavior.

To address this limitation, the stateUpdate type is now exported.
2026-04-20 17:12:10 +02:00
rjl493456442
7e388fd09e
core/state: separate trie reader to mptReader and ubtReader (#34763)
This PR separates the trie reader to mptTrieReader and ubtTrieReader for
improved readability and extensibility.

---------

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-20 15:04:42 +02:00
CPerezz
b6d415c88d
trie/bintrie: replace BinaryNode interface with GC-free NodeRef arena (#34055)
## Summary

Replace the `BinaryNode` interface with `NodeRef uint32` indices into
typed arena pools, eliminating GC-scanned pointers from binary trie
nodes.

Inspired by [fjl's
observation](https://github.com/ethereum/go-ethereum/pull/34034#issuecomment-4075176446):
> *"if the binary trie produces such a large graph, it should probably
be changed so that the trie node type does not contain pointers. The
runtime does not scan objects that do not contain pointers, so it can
really help with the performance to build it this way."*

### The problem

CPU profiling of the binary trie (EIP-7864) showed **44% of CPU time in
garbage collection**. Each `InternalNode` held two `BinaryNode`
interface values (2 pointer-words each), and the GC scanned every one.
With ~25K `InternalNode`s in memory during block processing, this
created enormous GC pressure.

### The solution

`NodeRef` is a compact `uint32` (2-bit kind tag + 30-bit pool index).
`NodeStore` manages chunked typed pools per node kind:
- **InternalNode pool**: ZERO Go pointers (children are `NodeRef`, hash
is `[32]byte`) → noscan spans
- **HashedNode pool**: ZERO Go pointers → noscan spans
- **StemNode pool**: retains `Values [][]byte` (matching existing
format)

The serialization format is unchanged — flat InternalNode
`[type][leftHash][rightHash]` = 65 bytes.

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

| Metric | Baseline | Arena | Delta |
|--------|----------|-------|-------|
| Approve (Mgas/s) | 374 | 382 | **+2.1%** |
| BalanceOf (Mgas/s) | 885 | 901 | **+1.8%** |
| Approve allocs/op | 775K | **607K** | **-21.7%** |
| BalanceOf allocs/op | 265K | **228K** | **-14.0%** |

## Benchmark: AMD EPYC 48-core (50GB state, execution-specs ERC-20, on
top of #34021 + #34032)

| Benchmark | Baseline | Arena | Delta |
|-----------|----------|-------|-------|
| erc20_approve (write) | 22.4 Mgas/s | **27.0 Mgas/s** | **+20.5%** |
| mixed_sload_sstore | 62.9 Mgas/s | **97.3 Mgas/s** | **+54.7%** |
| erc20_balanceof (read) | 180.8 Mgas/s | 167.6 Mgas/s | -7.3% (cold
cache variance) |

The arena benefit scales with heap size — the EPYC (larger heap, more GC
pressure) shows much larger gains than the M4 Pro (efficient unified
memory). The mixed workload baseline was unstable (62.9 vs 16.3 Mgas/s
between runs due to GC-induced throughput collapse); the arena
eliminates this entirely (95-97 Mgas/s, stable).

## Dependencies

Benchmarked with #34021 (H01 N+1 fix) + #34032 (R14 parallel hashing).
No code dependency — applies independently to master.

All test suites pass (`trie/bintrie` with `-race`, `core/state`,
`triedb/pathdb`, `cmd/geth`).

---------

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-04-20 14:08:30 +02:00
rjl493456442
29e0a6f404
core/vm, eth, tests: introduce gas budget (#34712)
Some checks are pending
/ 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
/ Linux Build (push) Waiting to run
This PR introduces a gasBudget struct to track the available gas for EVM
execution.

With the upcoming EIP-8037, multi-dimensional gas accounting will be
introduced, requiring multiple gas budget counters to be tracked 
simultaneously. To support this, the counters are grouped into a gasBudget 
structure.

This change is a prerequisite for internal refactoring in preparation
for EIP-8037.

---------

Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
2026-04-20 15:33:29 +08:00
rayoo
5af5510b1e
core/rawdb: fix file descriptor leak in freezer error paths (#34735)
In openFreezerFileForAppend, if Seek fails after the file is
successfully opened, the file handle is not closed, leaking a
descriptor.

Similarly in newTable, if opening the meta file fails, the
already-opened index file is not closed. And if newMetadata fails, both
the index and meta files are leaked.

Under repeated error conditions (e.g., corrupted filesystem), these
leaks accumulate and may exhaust the OS file descriptor limit, causing
cascading failures.
2026-04-20 11:06:17 +08:00
cui
8c7d61fcfe
tests: fix invalid eip parse error (#34750) 2026-04-20 11:02:42 +08:00
cui
78505e48dd
triedb/pathdb: fix typo (#34762) 2026-04-20 10:07:41 +08:00
CPerezz
53ff723cc7
core/state: handle *bintrie.BinaryTrie in mustCopyTrie (#34758)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
## Problem

`mustCopyTrie` in `core/state/database.go` panics on any trie type not
in its type switch:

```go
func mustCopyTrie(t Trie) Trie {
    switch t := t.(type) {
    case *trie.StateTrie:
        return t.Copy()
    case *transitiontrie.TransitionTrie:
        return t.Copy()
    default:
        panic(fmt.Errorf("unknown trie type %T", t))
    }
}
```

On UBT-backed databases (`state.NewUBTDatabase(...)`, used by
`blockchain.go:2124` when the triedb is configured for binary trie),
`StateDB.trie` is `*bintrie.BinaryTrie` — so every `StateDB.Copy()` call
(hit from `statedb.go:699` and the `*trie.StateTrie` branch of
`state_object.go:546`) crashes with `unknown trie type
*bintrie.BinaryTrie`.

## Fix

Add the `*bintrie.BinaryTrie` case. `BinaryTrie.Copy()` already exists
at `trie/bintrie/trie.go:372` and produces a correct deep copy — this
just wires it into the switch.
2026-04-18 18:47:22 +02:00
CPerezz
61bfacc52f
trie/bintrie: skip clean nodes in CollectNodes to reduce commit write amplification (#34754)
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
## Problem

`BinaryTrie.Commit` unconditionally walked every resolved in-memory node
and flushed it into the `NodeSet`, producing one Pebble write per
resolved internal + stem node on every block — even when the node's
on-disk blob was bitwise identical to the previous commit. On a warm
400M-state workload this meant tens of thousands of redundant 65-byte
writes per block, compounding Pebble compaction pressure on every
commit.

The existing `mustRecompute` flag tracks *hash* staleness, not
*disk-blob* staleness: after `Hash()` completes, `mustRecompute` is
cleared even though the fresh blob has not been persisted. It is
therefore insufficient for a skip-flush optimization.

## Fix

Mirror the MPT committer pattern (`trie/committer.go:51-56`) by adding a
`dirty` flag on `InternalNode` and `StemNode` with the semantics *the
on-disk blob is stale*. The flag is:

- set to `true` wherever the node is created or structurally modified
(the same call sites that already set `mustRecompute = true`);
- set to `false` only after the node has been passed to the `flushfn`
inside `CollectNodes`;
- left `false` on nodes produced by `DeserializeNodeWithHash`, matching
the *loaded from disk, already persisted* semantics.

`CollectNodes` short-circuits on `!dirty` subtrees. The propagation
invariant (an ancestor of any dirty node is itself dirty) is already
maintained by the existing `InsertValuesAtStem` / `Insert` paths, which
now mirror every `mustRecompute = true` setter with a `dirty = true`
setter.

## Benchmark

New `BenchmarkCollectNodes_SparseWrite` measures commit cost when only
one leaf changes between blocks — the common case for state updates.
10,000-stem trie, one-leaf modification + Commit per iteration, Apple M4
Pro:

| | before | after | delta |
|---|---|---|---|
| time / op | 12,653,000 ns | 7,336 ns | **~1,725×** |
| bytes / op | 107,224,740 B | 37,774 B | **~2,839×** |
| allocs / op | 80,953 | 134 | **~604×** |

End-to-end impact on a real workload depends on the
resolved-footprint-to-dirty-path ratio; the new
`TestBinaryTrieCommitIncremental` provides a structural regression guard
(asserts that a Commit following a single-leaf modification flushes a
root-to-leaf path, not the whole tree).

---

Found all of this stuff while bloating my #34706 DB to make some
benchmarks. And saw we were spending A LOT OF TIME on hashing.
Hope this helps the perf a bit. Will rebase the flat-state PR on top of
this once merged.
2026-04-18 11:42:58 +02:00
Snehendu Roy
573d94013c
core/rawdb: fix incorrect fsync ordering for index file truncation (#34728)
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-04-17 19:45:03 +08:00
Daniel Liu
4c03a0631e
cmd/evm: compare errors by value in timedExec instead of interface identity (#34733)
`timedExec` compares errors by direct interface inequality (haveErr !=
err). If execFunc returns newly constructed errors with the same message
each run, this will panic even though behavior is equivalent.
2026-04-17 19:43:53 +08:00
Edgar
89c1c16a46
cmd/geth: add code exporter for db export (#34696)
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
Adds a 'code' exporter to 'geth db export' that iterates over all
contract bytecode entries (CodePrefix + code_hash -> bytecode).

Usage: geth --datadir <dir> db export code code.rlp

This enables exporting contract bytecode.
2026-04-17 09:53:00 +08:00
Guillaume Ballet
ba215fd927
cmd, core, trie, triedb: split CachingDB into merkle + binary dbs. (#34700)
This Pr implements some prerequisite changes for #34004 : split the
`CachingDB` into a `MerkleDB` and a `UBTDB`, so that very different
behaviors don't clash as much.

The transition isn't handled by this PR, but after talking to Gary we
agreed that `UBTDB` should receive another `triedb`, which will only be
loaded if the `Ended` flag is set to false in the conversion contract.
If this is too hard to achieve, it makes sense to load it regardless,
and then loading can be prevented at a later stage by adding a
`UBTTransitionFinalizationTime` in `ChainConfig`.

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-04-17 08:55:54 +08:00
Sina M
f63e9f3a80
eth/tracers: fix codehash in prestate diffmode (#34675)
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 https://github.com/ethereum/go-ethereum/issues/34648.
2026-04-16 16:51:26 +08:00
Daniel Liu
b1baab4427
cmd/evm: fix trace.noreturndata usage string (#34731)
`trace.noreturndata` is documented as "enable return data output" but
the flag name/value imply it disables return data. This is confusing for
users and likely inverted wording. Update the Usage string to reflect
the actual behavior (disable return data output).
2026-04-16 16:16:53 +08:00
Jonny Rhea
d07a946a5b
log: allow –vmodule to downgrade log levels (#33111)
Changes the log handler to check for vmodule level overrides
even for messages above the current level. This enables the user to selectively
hide messages from certain packages, among other things.

Also fixes a bug where handler instances created by WithAttr would not follow
the level setting anymore. The WithAttrs method is calledd by slog.Logger.With,
which we also use in go-ethereum to create context specific loggers with
pre-filled attributes. Under the previous implementation of WithAttrs, if the
application created a long-lived logger (for example, for a specific peer), then
that logger would not be affected by later level changes done on the top-level
logger, leading to potentially missed events.

Closes: #30717

---------

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
Co-authored-by: Felix Lange <fjl@twurst.com>
2026-04-16 08:53:08 +02:00
Rahman
0b35ad95f5
cmd/utils: fix witness stats auto-enable to respect config file (#34729)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
Auto-enable logic for `StatelessSelfValidation` was reading CLI flag
directly via `ctx.Bool()`, bypassing the merged `cfg.EnableWitnessStats`
value. Now uses `cfg.EnableWitnessStats` so config file settings trigger
the same auto-enable behavior as CLI flags.
2026-04-16 11:17:01 +08:00
rjl493456442
ef0f1f96f9
core/state: ignore the root returned in Commit function for simplicity (#34723)
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
StateDB.Commit first commits all storage changes into the storage trie,
then updates the account metadata with the new storage root into the 
account trie.

Within StateDB.Commit, the new storage trie root has already been
computed and applied as the storage root. This PR explicitly skips the 
redundant storage trie root assignment for readability.
2026-04-15 11:15:43 +08:00
felipe
c9fea44616
eth/catalyst: respect slot num if specified in payload attributes for testing_buildBlockV1 (#34722)
This is a copy of #34721 but against `master` (rather than
`bal-devnet-3`), as requested by @jwasinger, since the slotnum logic now
exists on `master` as well.
2026-04-14 19:00:29 -04:00
cui
2253fce48d
core/types: remove redundant ')' (#34719)
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-04-14 22:09:17 +08:00
rjl493456442
eb67d61933
cmd/geth, core/state, tests: rework EIP7610 check (#34718)
This PR simplifies the implementation of EIP-7610 by eliminating the
need to check storage emptiness during contract deployment.

EIP-7610 specifies that contract creation must be rejected if the
destination account has a non-zero nonce, non-empty runtime code, or 
**non-empty storage**.

After EIP-161, all newly deployed contracts are initialized with a nonce
of one. As a result, such accounts are no longer eligible as deployment 
targets unless they are explicitly cleared.

However, prior to EIP-161, contracts were initialized with a nonce of
zero. This made it possible to end up with accounts that have:

- zero nonce
- empty runtime code
- non-empty storage (created during constructor execution)
- non-zero balance

These edge-case accounts complicate the storage emptiness check.

In practice, contract addresses are derived using one of the following
formulas:
- `Keccak256(rlp({sender, nonce}))[12:]`
- `Keccak256([]byte{0xff}, sender, salt[:], initHash)[12:]`

As such, an existing address is not selected as a deployment target
unless a collision occurs, which is extremely unlikely.

---

Previously, verifying storage emptiness relied on GetStorageRoot.
However, with the transition to the block-based access list (BAL), 
the storage root is no longer available, as computing it would require 
reconstructing the full storage trie from all mutations of preceding 
transactions.

To address this, this PR introduces a simplified approach: it hardcodes
the set of known accounts that have zero nonce, empty runtime code, 
but non-empty storage and non-zero balance. During contract deployment, 
if the destination address belongs to this set, the deployment is
rejected.

This check is applied retroactively back to genesis. Since no address
collision events have occurred in Ethereum’s history, this change does
not
alter existing behavior. Instead, it serves as a safeguard for future
state
transitions.
2026-04-14 15:54:36 +02:00
cui
2414861d36
core/state: optimize transient storage (#33695)
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
Optimizes the transient storage. Turns it from a map of maps into a single map keyed by <account,slot>.
2026-04-14 15:39:42 +02:00
jvn
c690d6041e
cmd/geth: add Prague pruning points for hoodi (#34714)
Adds config to add Prague prune point for the hoodi testnet.
2026-04-14 14:58:27 +02:00
Guillaume Ballet
c2234462a8
.github/workflows: add freebsd test github action (#34078)
This is meant to be run daily, in order to verify the FreeBSD build
wasn't broken like last time.
2026-04-14 14:47:43 +02:00
Csaba Kiraly
c453b99a57
cmd/devp2p/internal/v5test: fix hive test for discv5 findnode results (#34043)
This fixes the remaining Hive discv5/FindnodeResults failures in the
cmd/devp2p/internal/v5test fixture.

The issue was in the simulator-side bystander behavior, not in
production discovery logic. The existing fixture could get bystanders
inserted into the remote table, but under current geth behavior they
were not stable enough to remain valid FINDNODE results. In
particular, the fixture still had a few protocol/behavior mismatches:

- incomplete WHOAREYOU recovery
- replies not consistently following the UDP envelope source
- incorrect endpoint echoing in PONG
- fixture-originated PING using the wrong ENR sequence
- bystanders answering background FINDNODE with empty NODES

That last point was important because current lookup accounting can
treat repeatedly unhelpful FINDNODE interactions as failures. As a
result, a bystander could become live via PING/PONG and still later be
dropped from the table before the final FindnodeResults assertion.
This change updates the fixture so that bystanders behave more like
stable discv5 peers:

- perform one explicit initial handshake, then switch to passive response handling
- resend the exact challenged packet when handling WHOAREYOU
- reply to the actual UDP packet source and mirror that source in PONG.ToIP / PONG.ToPort
- use the bystander’s own ENR sequence in fixture-originated PING
- prefill each bystander with the bystander ENR set and answer FINDNODE from that set

The result is that the fixture now forms a small self-consistent lookup
environment instead of a set of peers that are live but systematically
poor lookup participants.
2026-04-14 12:15:39 +02:00
Charles Dusek
e1fe4a1a98
p2p/discover: fix flaky TestUDPv5_findnodeHandling (#34109)
Fixes #34108

The UDPv5 test harness (`newUDPV5Test`) uses the default `PingInterval`
of 3 seconds. When tests like `TestUDPv5_findnodeHandling` insert nodes
into the routing table via `fillTable`, the table's revalidation loop
may schedule PING packets for those nodes. Under the race detector or on
slow CI runners, the test runs long enough for revalidation to fire,
causing background pings to be written to the test pipe. The `close()`
method then finds these as unmatched packets and fails.

The fix sets `PingInterval` to a very large value in the test harness so
revalidation never fires during tests.

Verified locally: 100 iterations with `-race -count=100` pass reliably,
where previously the test would fail within ~50 iterations.
2026-04-14 09:43:44 +02:00
Marius Kjærstad
01e33d14be
build: upgrade -dlgo version to Go 1.25.9 (#34707)
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-04-13 16:32:40 +02:00
phrwlk
527ea11e50
core/vm/runtime: don't overwrite user input with default value (#33510)
runtime.setDefaults was unconditionally assigning cfg.Random =
&common.Hash{}, which silently overwrote any caller-provided Random
value. This made it impossible to simulate a specific PREVRANDAO and
also forced post-merge rules whenever London was active, regardless of
the intended environment.

This change only initializes cfg.Random when it is nil, matching how
other fields in Config are defaulted. Existing callers that did not set
Random keep the same behavior (a non-nil zero hash still enables
post-merge semantics), while callers that explicitly set Random now get
their value respected.
2026-04-13 15:46:13 +02:00
Conor Patrick
4da1e29320
signer/core/apitypes: fix encoding of opening parenthesis (#33702)
This fixes a truncation bug that results in an invalid serialization of
empty EIP712.

For example:

```json
{
    "method": "eth_signTypedData_v4",
    "request": {
        "types": {
            "EIP712Domain": [
                {
                    "name": "version",
                    "type": "string"
                }
            ],
            "Empty": []
        },
        "primaryType": "Empty",
        "domain": {
            "version": "0"
        },
        "message": {}
    }
}
``` 

When calculating the type-hash for the stuct-hash, it will incorrectly
use `Empty)` instead of `Empty()`
2026-04-13 15:30:36 +02:00
Vadim Tertilov
289826fefb
cmd/abigen/v2: add package-level errors (#34076)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
# Summary

Replaces the inline `errors.New("event signature mismatch")` in
generated `UnpackXxxEvent` methods with per-event package-level sentinel
errors (e.g. `ErrTransferSignatureMismatch`,
`ErrApprovalSignatureMismatch`), allowing callers to reliably
distinguish a topic mismatch from a genuine decoding failure via
`errors.Is`.

Each event gets its own sentinel, generated via the abigen template:

```go
var ErrTransferSignatureMismatch = errors.New("event signature mismatch")
```

This scoping is intentional — it allows callers to be precise about
*which* event was mismatched, which is useful when routing logs across
multiple unpackers.

# Motivation
Previously, all errors returned from `UnpackXxxEvent` were
indistinguishable without string matching. This is especially
problematic when processing logs sourced from `eth_getBlockReceipts`,
where a caller receives the full set of logs for a block across all
contracts and event types. In that context, a signature mismatch is
expected and should be skipped, while any other error (malformed data,
topic parsing failure) indicates something is genuinely wrong and should
halt execution:

```go
for _, log := range blockLogs {
    event, err := contract.UnpackTransferEvent(log)
    if errors.Is(err, gen.ErrTransferSignatureMismatch) {
        continue // not our event, expected
    }
    if err != nil {
        return fmt.Errorf("unexpected decode failure: %w", err) // alert
    }
    // process event
}
```

**Changes:**
- `abigen` template: generates a `ErrXxxSignatureMismatch` sentinel per
event and returns it on topic mismatch instead of an inline error
- Existing generated bindings & testdata: regenerated to reflect the
update

Implements #34075
2026-04-13 14:42:34 +02:00
Daniel Liu
5b7511eeed
core/vm: include operand in error message (#34635)
Return ErrInvalidOpCode with the executing opcode and offending
immediate for forbidden DUPN, SWAPN, and EXCHANGE operands. Extend
TestEIP8024_Execution to assert both opcode and operand for all
invalid-immediate paths.
2026-04-13 14:13:33 +02:00
Daniel Liu
7d463aedd3
accounts/keystore: fix flaky TestUpdatedKeyfileContents (#34084)
TestUpdatedKeyfileContents was intermittently failing with:

- Emptying account file failed
- wasn't notified of new accounts

Root cause: waitForAccounts required the account list match and an
immediately readable ks.changes notification in the same instant,
creating a timing race between cache update visibility and channel
delivery.

This change keeps the same timeout window but waits until both
conditions are observed, which preserves test intent while removing the
flaky timing dependency.

Validation:
- go test ./accounts/keystore -run '^TestUpdatedKeyfileContents$'
-count=100
2026-04-13 14:10:56 +02:00
bigbear
f7f57d29d4
crypto/bn256: fix comment in MulXi (#34659)
The comment formula showed (i+3) but the code multiplies by 9 (Lsh 3 +
add = 8+1).
This was a error when porting from upstream golang.org/x/crypto/bn256
where ξ=i+3.
Go-ethereum changed the constant to ξ=i+9 but forgot to update the inner
formula.
2026-04-13 13:57:11 +02:00
Gaurav Dhiman
ecae519972
beacon/engine, miner: fix testing_buildBlockV1 response (#34704)
Two fixes for `testing_buildBlockV1`:

1. Add `omitempty` to `SlotNumber` in `ExecutableData` so it is omitted
for pre-Amsterdam payloads. The spec defines the response as
`ExecutionPayloadV3` which does not include `slotNumber`.

2. Pass `res.fees` instead of `new(big.Int)` in `BuildTestingPayload` so
`blockValue` reflects actual priority fees instead of always being zero.

Corresponding fixture update: ethereum/execution-apis#783
2026-04-13 13:45:35 +02:00
Guillaume Ballet
735bfd121a
trie/bintrie: spec change, big endian hashing of slot key (#34670)
The spec has been changed during SIC #49, the offset is encoded as a
big-endian number.
2026-04-13 09:42:37 +02:00
Marius van der Wijden
6333855163
core: turn gas into a vector <regularGas, stateGas> (#34691)
Pre-refactor PR to get 8037 upstreamed in chunks

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-04-13 14:09:42 +08:00
CPerezz
deda47f6a1
trie/bintrie: fix GetAccount/GetStorage non-membership — verify stem before returning values (#34690)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
Fix `GetAccount` returning **wrong account data** for non-existent
addresses when the trie root is a `StemNode` (single-account trie) — the
`StemNode` branch returned `r.Values` without verifying the queried
address's stem matches.

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-04-10 19:43:48 +02:00
CPerezz
f71a884e37
trie/bintrie: fix DeleteAccount no-op (#34676)
`BinaryTrie.DeleteAccount` was a no-op, silently ignoring the caller's
deletion request and leaving the old `BasicData` and `CodeHash` in the
trie.

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-04-10 19:23:44 +02:00
cui
ea5448814f
core/filtermaps: remove dead condition check (#34695)
already check on line 40 before.
2026-04-10 17:41:59 +02:00
Guillaume Ballet
58557cb463
cmd/geth: add subcommand for offline binary tree conversion (#33740)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
This tool is designed for the offline translation of an MPT database to
a binary trie. This is to be used for users who e.g. want to prove
equivalence of a binary tree chain shadowing the MPT chain.

It adds a `bintrie` command, cleanly separating the concerns.
2026-04-09 10:27:19 +02:00
CPerezz
3772bb536a
triedb/pathdb: fix lookup sentinel collision with zero disk layer root (#34680) 2026-04-09 13:39:38 +08:00
Sina M
68c7058a80
core/stateless: fix parsing an empty witness (#34683)
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 is to fix a crasher in keeper.
2026-04-09 09:19:54 +08:00
Felföldi Zsolt
21b19362c2
core/state: fix tracer hook for EIP-7708 burn logs (#34688)
This PR fixes https://github.com/ethereum/go-ethereum/issues/34623 by
changing the `vm.StateDB` interface: 

Instead of `EmitLogsForBurnAccounts()` emitting burn logs, `LogsForBurnAccounts()
[]*types.Log` just returns these logs which are then emitted by the caller. 

This way when tracing is used, `hookedStateDB.AddLog` will be used 
automatically and there is no need to duplicate either the burn log
logic or the `OnLog` tracing hook.
2026-04-09 09:12:35 +08:00
Mael Regnery
a8ea6319f1
eth/filters: return -32602 when exceeding the block range limit (#34647)
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
Co-authored-by: Felix Lange <fjl@twurst.com>
2026-04-08 12:57:29 +02:00
DELENE-TCHIO
04e40995d9
core: merge access events for all system calls (#34637)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
ProcessBeaconBlockRoot (EIP-4788) and processRequestsSystemCall
(EIP-7002/7251) do not merge the EVM access events into the state after
execution. ProcessParentBlockHash (EIP-2935) already does this correctly
at line 290-291.

Without this merge, the Verkle witness will be missing the storage
accesses from the beacon root and request system calls, leading to
incomplete witnesses and potential consensus issues when Verkle
activates.
2026-04-07 21:55:09 +02:00
locoholy
9878ef926d
ethclient: omit empty address/topics fields in RPC filter requests (#33884)
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
Changes JSON serialization of FilterCriteria to exclude "address" when it is empty.
2026-04-07 18:01:26 +02:00
cui
0bafb29490
core/types: add accessList to WithSeal and WithBody (#34651)
Co-authored-by: Felix Lange <fjl@twurst.com>
2026-04-07 22:04:07 +08:00
Diego López León
52b8c09fdf
triedb/pathdb: skip duplicate-root layer insertion (#34642)
PathDB keys diff layers by state root, not by block hash. That means a
side-chain block can legitimately collide with an existing canonical diff layer
when both blocks produce the same post-state (for example same parent, 
same coinbase, no txs).

Today `layerTree.add` blindly inserts that second layer. If the root
already exists, this overwrites `tree.layers[root]` and appends the same 
root to the mutation lookup again. Later account/storage lookups resolve 
that root to the wrong diff layer, which can corrupt reads for descendant 
canonical states.

At runtime, the corruption is silent: no error is logged and no invariant check
fires. State reads against affected descendants simply return stale data
from the wrong diff layer (for example, an account balance that reflects one
fewer block reward), which can propagate into RPC responses and block 
validation.

This change makes duplicate-root inserts idempotent. A second layer with
the same state root does not add any new retrievable state to a tree that is
already keyed by root; keeping the original layer preserves the existing parent 
chain and avoids polluting the lookup history with duplicate roots.

The regression test imports a canonical chain of two layers followed by
a fork layer at height 1 with the same state root but a different block hash. 
Before the fix, account and storage lookups at the head resolve the fork 
layer instead of the canonical one. After the fix, the duplicate insert is 
skipped and lookups remain correct.
2026-04-07 21:31:41 +08:00
rjl493456442
b5d322000c
eth/protocols/snap: fix block accessList encoding rule (#34644)
This PR refactors the encoding rules for `AccessListsPacket` in the wire
protocol. Specifically:

- The response is now encoded as a list of `rlp.RawValue`
- `rlp.EmptyString` is used as a placeholder for unavailable BAL objects
2026-04-07 20:13:19 +08:00
Jonny Rhea
bd6530a1d4
triedb, triedb/internal, triedb/pathdb: add GenerateTrie + extract shared pipeline into triedb/internal (#34654)
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 adds `GenerateTrie(db, scheme, root)` to the `triedb` package,
which rebuilds all tries from flat snapshot KV data. This is needed by
snap/2 sync so it can rebuild the trie after downloading the flat state.
The shared trie generation pipeline from `pathdb/verifier.go` was moved
into `triedb/internal/conversion.go` so both `GenerateTrie` and
`VerifyState` reuse the same code.
2026-04-07 14:36:53 +08:00
Martin HS
44257950f1
tests: enable execution of amsterdam statetests (#34671)
👋

This PR makes it possible to run "Amsterdam" in statetests. I'm aware
that they'll be failing and not in consensus with other clients, yet,
but it's nice to be able to run tests and see what works and what
doesn't

Before the change: 
```
$ go run ./cmd/evm statetest ./amsterdam.json 
[
  {
    "name": "00000019-mixed-1",
    "pass": false,
    "fork": "Amsterdam",
    "error": "unexpected error: unsupported fork \"Amsterdam\""
  }
]
```
After
```
$ go run ./cmd/evm statetest ./amsterdam.json 
{"stateRoot": "0x25b78260b76493a783c77c513125c8b0c5d24e058b4e87130bbe06f1d8b9419e"}
[
  {
    "name": "00000019-mixed-1",
    "pass": false,
    "stateRoot": "0x25b78260b76493a783c77c513125c8b0c5d24e058b4e87130bbe06f1d8b9419e",
    "fork": "Amsterdam",
    "error": "post state root mismatch: got 25b78260b76493a783c77c513125c8b0c5d24e058b4e87130bbe06f1d8b9419e, want 0000000000000000000000000000000000000000000000000000000000000000"
  }
]
```
2026-04-07 14:13:25 +08:00
rjl493456442
d8cb8a962b
core, eth, ethclient, triedb: report trienode index progress (#34633)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
The trienode history indexing progress is also exposed via an RPC 
endpoint and contributes to the eth_syncing status.
2026-04-04 21:00:07 +08:00
Jonny Rhea
a608ac94ec
eth/protocols/snap: restore Bytes soft limit to GetAccessListsPacket (#34649)
This PR adds Bytes field back to GetAccesListsPacket
2026-04-04 20:53:54 +08:00
Jonny Rhea
00da4f51ff
core, eth/protocols/snap: Snap/2 Protocol + BAL Serving (#34083)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
Implement the snap/2 wire protocol with BAL serving

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-04-03 14:10:32 +08:00
rjl493456442
0ba4314321
core/state: introduce state iterator interface (#33102)
In this PR, the Database interface in `core/state` has been extended
with one more function:

```go
	// Iteratee returns a state iteratee associated with the specified state root,
	// through which the account iterator and storage iterator can be created.
	Iteratee(root common.Hash) (Iteratee, error)
```

With this additional abstraction layer, the implementation details can be hidden
behind the interface. For example, state traversal can now operate directly on 
the flat state for Verkle or binary trees, which do not natively support traversal.

Moreover, state dumping will now prefer using the flat state iterator as
the primary option, offering better efficiency.


Edit: this PR also fixes a tiny issue in the state dump, marshalling the
next field in the correct way.
2026-04-03 10:35:32 +08:00
cui
bcb0efd756
core/types: copy block access list hash in CopyHeader (#34636)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
2026-04-02 20:40:45 +08:00
rjl493456442
db6c7d06a2
triedb/pathdb: implement history index pruner (#33999)
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 implements the missing functionality for archive nodes by 
pruning stale index data.

The current mechanism is relatively simple but sufficient for now: 
it periodically iterates over index entries and deletes outdated data 
on a per-block basis. 

The pruning process is triggered every 90,000 new blocks (approximately 
every 12 days), and the iteration typically takes ~30 minutes on a 
mainnet node.

This mechanism is only applied with `gcmode=archive` enabled, having
no impact on normal full node.
2026-04-02 00:21:58 +02:00
Daniel Liu
14a26d9ccc
eth/gasestimator: fix block overrides in estimate gas (#34081)
Block overrides were to a great extent ignored by the gasestimator. This PR
fixes that.
2026-04-01 20:32:17 +02:00
Felföldi Zsolt
fc43170cdd
beacon/light: keep retrying checkpoint init if failed (#33966)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Docker Image (push) Waiting to run
This PR changes the blsync checkpoint init logic so that even if the
initialization fails with a certain server and an error log message is
printed, the server goes back to its initial state and is allowed to
retry initialization after the failure delay period. The previous logic
had an `ssDone` server state that did put the server in a permanently
unusable state once the checkpoint init failed for an apparently
permanent reason. This was not the correct behavior because different
servers behave differently in case of overload and sometimes the
response to a permanently missing item is not clearly distinguishable
from an overload response. A safer logic is to never assume anything to
be permanent and always give a chance to retry.
The failure delay formula is also fixed; now it is properly capped at
`maxFailureDelay`. The previous formula did allow the delay to grow
unlimited if a retry was attempted immediately after each delay period.
2026-04-01 16:05:57 +02:00
Chase Wright
92b4cb2663
eth/tracers/logger: conform structLog tracing to spec (#34093)
Some checks failed
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Linux Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
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>
2026-03-31 16:02:40 +02: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
Jonny Rhea
dc3794e3dc
core/rawdb: BAL storage layer (#34064)
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
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>
2026-03-31 15:05:31 +08:00
Bosul Mun
965bd6b6a0
eth: implement EIP-7975 (eth/70 - partial block receipt lists) (#33153)
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
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>
2026-03-30 15:17:37 +02:00
rjl493456442
fe47c39903
version: start v1.17.3 release cycle (#34619) 2026-03-30 15:01:29 +02:00
rjl493456442
be4dc0c4be
version: release go-ethereum v1.17.2 stable (#34618) 2026-03-30 18:42:40 +08:00
Sina M
95705e8b7b
internal/ethapi: limit number of getProofs keys (#34617)
We can consider making this limit configurable if ever the need arose.
2026-03-30 16:01:30 +08:00
Sina M
ceabc39304
internal/ethapi: limit number of calls to eth_simulateV1 (#34616)
Later on we can consider making these limits configurable if the
use-case arose.
2026-03-30 16:01:12 +08:00
Charles Dusek
e585ad3b42
core/rawdb: fix freezer dir.Sync() failure on Windows (#34115) 2026-03-30 15:34:23 +08:00
Daniel Liu
d1369b69f5
core/txpool/legacypool: use types.Sender instead of signer.Sender (#34059)
Some checks failed
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Linux Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
`pool.signer.Sender(tx)` bypasses the sender cache used by types.Sender,
which can force an extra signature recovery for every promotable tx
(promotion runs frequently). Use `types.Sender(pool.signer, tx)` here to
keep sender derivation cached and consistent.
2026-03-28 11:46:09 +01:00
Guillaume Ballet
bd3c8431d9
build, cmd/keeper: add "womir" target (#34079)
This PR enables the block validation of keeper in the womir/openvm zkvm.

It also fixes some issues related to building the executables in CI.
Namely, it activates the build which was actually disabled, and also
resolves some resulting build conflicts by fixing the tags.

Co-authored-by: Leo <leo@powdrlabs.com>
2026-03-28 11:39:44 +01:00
Charles Dusek
a2496852e9
p2p/discover: resolve DNS hostnames for bootstrap nodes (#34101)
Fixes #31208
2026-03-28 11:37:39 +01: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
jwasinger
acdd139717
miner: set slot number when building test payload (#34094)
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-27 09:45:49 +08:00
Daniel Liu
1b3b028d1d
miner: fix txFitsSize comment (#34100)
Rename the comment so it matches the helper name.
2026-03-27 09:41:56 +08:00
Lessa
8a3a309fa9
core/txpool/legacypool: remove redundant nil check in Get (#34092)
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
Leftover from d40a255 when return type changed from *txpool.Transaction
to *types.Transaction.
2026-03-26 14:02:31 +01:00
bigbear
5d0e18f775
core/tracing: fix NonceChangeAuthorization comment (#34085)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
Comment referenced NonceChangeTransaction which doesn't exist, should be
NonceChangeAuthorization.
2026-03-25 09:16:09 +01:00
Andrew Davis
8f9061f937
cmd/utils: optimize history import with batched insertion (#33894)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
Improve speed of import-history command by two orders of magnitude.

Rework ImportHistory to collect up to 2500 blocks per flush instead of
flushing after each block, reducing database commit overhead.

---------

Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2026-03-24 21:47:18 +01:00
Csaba Kiraly
e951bcbff7
cmd/devp2p: fix discv5 PingMultiIP test session key mismatch (#34031)
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
conn.read() used the actual UDP packet source address for
codec.Decode(), but conn.write() always used tc.remoteAddr. When the
remote node is reachable via multiple Docker networks, the packet source
IP differs from tc.remoteAddr, causing a session key lookup failure in
the codec.

Use tc.remoteAddr.String() consistently in conn.read() so the session
cache key matches what was used during Encode.
2026-03-24 07:57:11 -06:00
vickkkkkyy
745b0a8c09
cmd/utils: guard SampleRatio flag with IsSet check (#34062)
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
In `setOpenTelemetry`, all other fields (Enabled, Endpoint, AuthUser,
AuthPassword, InstanceID, Tags) are guarded by `ctx.IsSet()` checks, so
they only override the config file when explicitly set via CLI flags.
`SampleRatio` was the only field missing this guard, causing the flag
default (`1.0`) to always overwrite whatever was loaded from the config
file.

- Fix OpenTelemetry `SampleRatio` being unconditionally overwritten by
the CLI flag default value (`1.0`), even when the user did not pass
`--rpc.telemetry.sample-ratio`
- This caused config file values for `SampleRatio` to be silently
ignored
2026-03-23 13:14:28 -04: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
Daniel Liu
a61e5ccb1e
core, internal/ethapi: fix incorrect max-initcode RPC error mapping (#34067)
Problem:

The max-initcode sentinel moved from core to vm, but RPC pre-check
mapping still depended on core.ErrMaxInitCodeSizeExceeded. This mismatch
could surface inconsistent error mapping when oversized initcode is
submitted through JSON-RPC.

Solution:

- Remove core.ErrMaxInitCodeSizeExceeded from the core pre-check error
set.
- Map max-initcode validation errors in RPC from
vm.ErrMaxInitCodeSizeExceeded.
- Keep the RPC error code mapping unchanged (-38025).

Impact:

- Restores consistent max-initcode error mapping after the sentinel
move.
- Preserves existing JSON-RPC client expectations for error code -38025.
- No consensus, state, or protocol behavior changes.
2026-03-23 22:10:32 +08:00
Lessa
e23b0cbc22
core/rawdb: fix key length check for num -- hash in db inspect (#34074)
Fix incorrect key length calculation for `numHashPairings` in
`InspectDatabase`, introduced in #34000.

The `headerHashKey` format is `headerPrefix + num + headerHashSuffix`
(10 bytes), but the check incorrectly included `common.HashLength`,
expecting 42 bytes.

This caused all number -- hash entries to be misclassified as
unaccounted data.
2026-03-23 21:54:30 +08:00
Guillaume Ballet
305cd7b9eb
trie/bintrie: fix NodeIterator Empty node handling and expose tree accessors (#34056)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
Fix three issues in the binary trie NodeIterator:

1. Empty nodes now properly backtrack to parent and continue iteration
instead of terminating the entire walk early.

2. `HashedNode` resolver handles `nil` data (all-zeros hash) gracefully
by treating it as Empty rather than panicking.

3. Parent update after node resolution guards against stack underflow
when resolving the root node itself.

---------

Co-authored-by: tellabg <249254436+tellabg@users.noreply.github.com>
2026-03-20 13:53:14 -04: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
jvn
59ce2cb6a1
p2p: track in-progress inbound node IDs (#33198)
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
Avoid dialing a node while we have an inbound
connection request from them in progress.

Closes #33197
2026-03-20 05:52:15 +01:00
Felix Lange
35b91092c5
rlp: add Size method to EncoderBuffer (#34052)
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
The new method returns the size of the written data, excluding any
unfinished list structure.
2026-03-19 18:26:00 +01:00
jwasinger
fd859638bd
core/vm: rework gas measurement for call variants (#33648)
EIP-7928 brings state reads into consensus by recording accounts and storage accessed during execution in the block access list. As part of the spec, we need to check that there is enough gas available to cover the cost component which doesn't depend on looking up state. If this component can't be covered by the available gas, we exit immediately.

The portion of the call dynamic cost which doesn't depend on state look ups:

- EIP2929 call costs
- value transfer cost
- memory expansion cost

This PR:

- breaks up the "inner" gas calculation for each call variant into a pair of stateless/stateful cost methods
- modifies the gas calculation logic of calls to check stateless cost component first, and go out of gas immediately if it is not covered.

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-03-19 10:02:49 -06:00
rjl493456442
a3083ff5d0
cmd: add support for enumerating a single storage trie (#34051)
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-19 09:52:10 +01:00
Bosul Mun
4faadf17fb
rlp: add AppendList method to RawList (#34048)
This the AppendList method to merge two RawList instances by
appending the raw content.
2026-03-19 09:51:03 +01:00
vickkkkkyy
3341d8ace0
eth/filters: rangeLogs should error on invalid block range (#33763)
Some checks are pending
/ Keeper Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
Fixes log filter to reject out of order block ranges.
2026-03-18 23:31:40 +01:00
haoyu-haoyu
b35645bdf7
build: fix missing '!' in shebang of generated oss-fuzz scripts (#34044)
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
\`oss-fuzz.sh\` line 38 writes \`#/bin/sh\` instead of \`#!/bin/sh\` as
the shebang of generated fuzz test runner scripts.

\`\`\`diff
-#/bin/sh
+#!/bin/sh
\`\`\`

Without the \`!\`, the kernel does not recognize the interpreter
directive.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 13:56:26 +01:00
Sina M
6ae3f9fa56
core/history: refactor pruning configuration (#34036)
This PR introduces a new type HistoryPolicy which captures user intent
as opposed to pruning point stored in the blockchain which persists the
actual tail of data in the database.

It is in preparation for the rolling history expiry feature.

It comes with a semantic change: if database was pruned and geth is
running without a history mode flag (or explicit keep all flag) geth
will emit a warning but continue running as opposed to stopping the
world.
2026-03-18 13:54:29 +01:00
CPerezz
6138a11c39
trie/bintrie: parallelize InternalNode.Hash at shallow tree depths (#34032)
## Summary

At tree depths below `log2(NumCPU)` (clamped to [2, 8]), hash the left
subtree in a goroutine while hashing the right subtree inline. This
exploits available CPU cores for the top levels of the tree where
subtree hashing is most expensive. On single-core machines, the parallel
path is disabled entirely.

Deeper nodes use sequential hashing with the existing `sync.Pool` hasher
where goroutine overhead would exceed the hash computation cost. The
parallel path uses `sha256.Sum256` with a stack-allocated buffer to
avoid pool contention across goroutines.

**Safety:**
- Left/right subtrees are disjoint — no shared mutable state
- `sync.WaitGroup` provides happens-before guarantee for the result
- `defer wg.Done()` + `recover()` prevents goroutine panics from
crashing the process
- `!bt.mustRecompute` early return means clean nodes never enter the
parallel path
- Hash results are deterministic regardless of computation order — no
consensus risk

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

| Metric | Baseline | Parallel | Delta |
|--------|----------|----------|-------|
| Approve (Mgas/s) | 224.5 ± 7.1 | **259.6 ± 2.4** | **+15.6%** |
| BalanceOf (Mgas/s) | 982.9 ± 5.1 | 954.3 ± 10.8 | -2.9% (noise, clean
nodes skip parallel path) |
| Allocs/op (approve) | ~810K | ~700K | -13.6% |
2026-03-18 13:54:23 +01:00
Mayveskii
b6115e9a30
core: fix txLookupLock mutex leak on error returns in reorg() (#34039)
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-18 15:43:24 +08:00
felipe
ab357151da
cmd/evm: don't strip prefixes on requests over t8n (#33997)
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
Found this bug while implementing the Amsterdam changes t8n changes for
benchmark test filling in EELS.

Prefixes were incorrectly being stripped on requests over t8n and this
was leading to `fill` correctly catching hash mismatches on the EELS
side for some BAL tests. Though this was caught there, I think this
change might as well be cherry-picked there instead and merged to
`master`.

This PR brings this behavior to parity with EELS for Osaka filling.
There are still some quirks with regards to invalid block tests but I
did not investigate this further.
2026-03-17 16:07:28 +01:00
rjl493456442
9b2ce121dc
triedb/pathdb: enhance history index initer (#33640)
This PR improves the pbss archive mode. Initial sync
of an archive mode which has the --gcmode archive
flag enabled will be significantly sped up.

It achieves that with the following changes:

The indexer now attempts to process histories in batch whenever
possible.
Batch indexing is enforced when the node is still syncing and the local
chain
head is behind the network chain head. 

In this scenario, instead of scheduling indexing frequently alongside
block
insertion, the indexer waits until a sufficient amount of history has
accumulated
and then processes it in a batch, which is significantly more efficient.

---------

Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-17 15:29:30 +01:00
Sina M
fc1b0c0b83
internal/ethapi: warn on reaching global gas cap for eth_simulateV1 (#34016)
Warn user when gas limit of a tx is capped due to rpc server's gas cap
being reached.
2026-03-17 13:52: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
Jonny Rhea
98b13f342f
miner: add OpenTelemetry spans for block building path (#33773)
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
Instruments the block building path with OpenTelemetry tracing spans.

- added spans in forkchoiceUpdated -> buildPayload -> background payload
loop -> generateWork iterations. Spans should look something like this:

```
jsonrpc.engine/forkchoiceUpdatedV3
|- rpc.runMethod
|  |- engine.forkchoiceUpdated
|     |- miner.buildPayload [payload.id, parent.hash, timestamp]
|        |- miner.generateWork [txs.count, gas.used, fees] (empty block)
|        |  |- miner.prepareWork
|        |  |- miner.FinalizeAndAssemble
|        |     |- consensus.beacon.FinalizeAndAssemble [block.number, txs.count, withdrawals.count]
|        |        |- consensus.beacon.Finalize
|        |        |- consensus.beacon.IntermediateRoot
|        |        |- consensus.beacon.NewBlock
|        |- miner.background [block.number, iterations.total, exit.reason, empty.delivered]
|           |- miner.buildIteration [iteration, update.accepted]
|           |  |- miner.generateWork [txs.count, gas.used, fees]
|           |     |- miner.prepareWork
|           |     |- miner.fillTransactions [pending.plain.count, pending.blob.count]
|           |     |  |- miner.commitTransactions.priority (if prio txs exist)
|           |     |  |  |- miner.commitTransactions
|           |     |  |     |- miner.commitTransaction (per tx)
|           |     |  |- miner.commitTransactions.normal (if normal txs exist)
|           |     |     |- miner.commitTransactions
|           |     |        |- miner.commitTransaction (per tx)
|           |     |- miner.FinalizeAndAssemble
|           |        |- consensus.beacon.FinalizeAndAssemble [block.number, txs.count, withdrawals.count]
|           |           |- consensus.beacon.Finalize
|           |           |- consensus.beacon.IntermediateRoot
|           |           |- consensus.beacon.NewBlock
|           |- miner.buildIteration [iteration, update.accepted]
|           |  |- ...
|           |- ...

```

- added simulated server spans in SimulatedBeacon.sealBlock so dev mode
(geth --dev) produces traces that mirror production Engine API calls
from a real consensus client.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-03-16 19:24:41 +01:00
rjl493456442
a7d09cc14f
core: fix code database initialization in stateless mode (#34011)
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
This PR fixes the statedb initialization, ensuring the data source is
bound with the stateless input.
2026-03-16 09:45:26 +01:00
Guillaume Ballet
77e7e5ad1a
go.mod, go.sum: update karalabe/hid to fix broken FreeBSD ports build (#34008)
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
cgo builds have been broken in FreeBSD ports because of the hid lib.
@enriquefynn has made a temporary patch, but the fix has been merged in
the master branch, so let's reflect that here.
2026-03-16 14:35:07 +08:00
vickkkkkyy
24025c2bd0
build: fix signify flag name in doWindowsInstaller (#34006)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
The signify flag in `doWindowsInstaller` was defined as "signify key"
(with a space), making it impossible to pass via CLI (`-signify
<value>`). This meant the Windows installer signify signing was silently
never executed.

Fix by renaming the flag to "signify", consistent with `doArchive` and
`doKeeperArchive`.
2026-03-14 10:22:50 +01:00
jwasinger
ede376af8e
internal/ethapi: encode slotNumber as hex in RPCMarshalHeader (#34005)
Some checks are pending
/ Windows Build (push) Waiting to run
/ 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
The slotNumber field was being passed as a raw *uint64 to the JSON
marshaler, which serializes it as a plain decimal integer (e.g. 159).
All Ethereum JSON-RPC quantity fields must be hex-encoded per spec.

Wrap with hexutil.Uint64 to match the encoding of other numeric header
fields like blobGasUsed and excessBlobGas.

Co-authored-by: qu0b <stefan@starflinger.eu>
2026-03-13 17:09:32 +01:00
vickkkkkyy
189f9d0b17
eth/filters: check history pruning cutoff in GetFilterLogs (#33823)
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
Return proper error for the log filters going beyond pruning
point on a node with expired history.
2026-03-13 13:26:20 +01:00
Lessa
dba741fd31
console: fix autocomplete digit range to include 0 (#34003)
PR #26518 added digit support but used '1'-'9' instead of '0'-'9'. This
breaks autocomplete for identifiers containing 0 like account0.
2026-03-13 12:39:45 +01:00
Lee Gyumin
eaa9418ac1
core/rawdb: enforce exact key length for num->hash and td in db inspect (#34000)
This PR improves `db inspect` classification accuracy in
`core/rawdb/database.go` by tightening key-shape checks for:

- `Block number->hash`
- `Difficulties (deprecated)`

Previously, both categories used prefix/suffix heuristics and could
mis-bucket unrelated entries.
2026-03-13 09:45:14 +01:00
Guillaume Ballet
1c9ddee16f
trie/bintrie: use a sync.Pool when hashing binary tree nodes (#33989)
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
Binary tree hashing is quite slow, owing to many factors. One of them is
the GC pressure that is the consequence of allocating many hashers, as a
binary tree has 4x the size of an MPT. This PR introduces an
optimization that already exists for the MPT: keep a pool of hashers, in
order to reduce the amount of allocations.
2026-03-12 10:20:12 +01:00
jvn
95b9a2ed77
core: Implement eip-7954 increase Maximum Contract Size (#33832)
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
Implement EIP7954, This PR raises the maximum contract code size
to 32KiB and initcode size to 64KiB , following https://eips.ethereum.org/EIPS/eip-7954

---------

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2026-03-12 10:23:49 +08:00
Copilot
de0a452f7d
eth/filters: fix race in pending tx and new heads subscriptions (#33990)
`TestSubscribePendingTxHashes` hangs indefinitely because pending tx
events are permanently missed due to a race condition in
`NewPendingTransactions` (and `NewHeads`). Both handlers called their
event subscription functions (`SubscribePendingTxs`,
`SubscribeNewHeads`) inside goroutines, so the RPC handler returned the
subscription ID to the client before the filter was installed in the
event loop. When the client then sent a transaction, the event fired but
no filter existed to catch it — the event was silently lost.

- Move `SubscribePendingTxs` and `SubscribeNewHeads` calls out of
goroutines so filters are installed synchronously before the RPC
response is sent, matching the pattern already used by `Logs` and
`TransactionReceipts`

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in
our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: s1na <1591639+s1na@users.noreply.github.com>
2026-03-12 10:21:45 +08:00
rjl493456442
7d13acd030
core/rawdb, triedb/pathdb: enable trienode history alongside existing data (#33934)
Fixes https://github.com/ethereum/go-ethereum/issues/33907

Notably there is a behavioral change:
- Previously Geth will refuse to restart if the existing trienode
history is gapped with the state data
- With this PR, the gapped trienode history will be entirely reset and
being constructed from scratch
2026-03-12 09:21:54 +08:00
Guillaume Ballet
59512b1849
cmd/fetchpayload: add payload-building utility (#33919)
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 adds a cmd tool fetchpayload which connects to a
node and gets all the information in order to create a serialized
payload that can then be passed to the zkvm.
2026-03-11 16:18:42 +01:00
Sina M
3c20e08cba
cmd/geth: add Prague pruning points (#33657)
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 allows users to prune their nodes up to the Prague fork. It
indirectly depends on #32157 and can't really be merged before eraE
files are widely available for download.

The `--history.chain` flag becomes mandatory for `prune-history`
command. Here I've listed all the edge cases that can happen and how we
behave:

## prune-history Behavior

| From        | To           | Result                   |
|-------------|--------------|--------------------------|
| full        | postmerge    |  prunes                |
| full        | postprague   |  prunes                |
| postmerge   | postprague   |  prunes further        |
| postprague  | postmerge    |  can't unprune         |
| any         | all          |  use import-history    |


## Node Startup Behavior

| DB State | Flag | Result |

|-------------|--------------|----------------------------------------------------------------|
| fresh | postprague |  syncs from Prague |
| full | postprague |  "run prune-history first" |
| postmerge | postprague |  "run prune-history first" |
| postprague | postmerge |  "can't unprune, use import-history or fix
flag" |
| pruned | all |  accepts known prune points |
2026-03-11 12:47:42 +01:00
bigbear
88f8549d37
cmd/geth: correct misleading flag description in removedb command (#33984)
The `--remove.chain` flag incorrectly described itself as selecting
"state data" for removal, which could mislead operators into removing
the wrong data category. This corrects the description to accurately
reflect that the flag targets chain data (block bodies and receipts).
2026-03-11 16:33:10 +08:00
jwasinger
32f05d68a2
core: end telemetry span for ApplyTransactionWithEVM if error is returned (#33955) 2026-03-11 14:41:43 +08:00
georgehao
f6068e3fb2
eth/tracers: fix accessList StorageKeys return null (#33976)
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-11 11:46:49 +08:00
rjl493456442
27c4ca9df0
eth: resolve finalized from disk if it's not recently announced (#33150)
This PR contains two changes:

Firstly, the finalized header will be resolved from local chain if it's
not recently announced via the `engine_newPayload`. 

What's more importantly is, in the downloader, originally there are two
code paths to push forward the pivot point block, one in the beacon 
header fetcher (`fetchHeaders`), and another one is in the snap content 
processer (`processSnapSyncContent`).

Usually if there are new blocks and local pivot block becomes stale, it
will firstly be detected by the `fetchHeaders`. `processSnapSyncContent` 
is fully driven by the beacon headers and will only detect the stale pivot 
block after synchronizing the corresponding chain segment. I think the 
detection here is redundant and useless.
2026-03-11 11:23:00 +08:00
Sina M
aa417b03a6
core/tracing: fix nonce revert edge case (#33978)
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
We got a report for a bug in the tracing journal which has the
responsibility to emit events for all state that must be reverted.

The edge case is as follows: on CREATE operations the nonce is
incremented. When a create frame reverts, the nonce increment associated
with it does **not** revert. This works fine on master. Now one step
further: if the parent frame reverts tho, the nonce **should** revert
and there is the bug.
2026-03-10 16:53:21 +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
b8a3fa7d06
cmd/utils, eth/ethconfig: change default cache settings (#33975)
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 fixes a regression introduced in https://github.com/ethereum/go-ethereum/pull/33836/changes

Before PR 33836, running mainnet would automatically bump the cache size
to 4GB and trigger a cache re-calculation, specifically setting the key-value 
database cache to 2GB.
 
After PR 33836, this logic was removed, and the cache value is no longer
recomputed if no command line flags are specified. The default key-value 
database cache is 512MB.

This PR bumps the default key-value database cache size alongside the
default cache size for other components (such as snapshot) accordingly.
2026-03-09 23:18:18 +08:00
Muzry
b08aac1dbc
eth/catalyst: allow getPayloadV2 for pre-shanghai payloads (#33932)
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
I observed failing tests in Hive `engine-withdrawals`:

-
https://hive.ethpandaops.io/#/test/generic/1772351960-ad3e3e460605c670efe1b4f4178eb422?testnumber=146
-
https://hive.ethpandaops.io/#/test/generic/1772351960-ad3e3e460605c670efe1b4f4178eb422?testnumber=147

```shell
  DEBUG (Withdrawals Fork on Block 2): NextPayloadID before getPayloadV2:
  id=0x01487547e54e8abe version=1
  >> engine_getPayloadV2("0x01487547e54e8abe")
  << error: {"code":-38005,"message":"Unsupported fork"}
  FAIL: Expected no error on EngineGetPayloadV2: error=Unsupported fork
```
 
The same failure pattern occurred for Block 3.

Per Shanghai engine_getPayloadV2 spec, pre-Shanghai payloads should be
accepted via V2 and returned as ExecutionPayloadV1:
- executionPayload: ExecutionPayloadV1 | ExecutionPayloadV2
- ExecutionPayloadV1 MUST be returned if payload timestamp < Shanghai
timestamp
- ExecutionPayloadV2 MUST be returned if payload timestamp >= Shanghai
timestamp

Reference:
-
https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md#engine_getpayloadv2

Current implementation only allows GetPayloadV2 on the Shanghai fork
window (`[]forks.Fork{forks.Shanghai}`), so pre-Shanghai payloads are
rejected with Unsupported fork.

If my interpretation of the spec is incorrect, please let me know and I
can adjust accordingly.

---------

Co-authored-by: muzry.li <muzry.li1@ambergroup.io>
2026-03-09 11:22:58 +01:00
Marius van der Wijden
00540f9469
go.mod: update go-eth-kzg (#33963)
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
Updates go-eth-kzg to
https://github.com/crate-crypto/go-eth-kzg/releases/tag/v1.5.0
Significantly reduces the allocations in VerifyCellProofBatch which is
around ~5% of all allocations on my node

---------

Co-authored-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
2026-03-08 11:44:29 +01:00
cui
e15d4ccc01
core/types: reduce alloc in hot code path (#33523)
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
Reduce allocations in calculation of tx cost.

---------

Co-authored-by: weixie.cui <weixie.cui@okg.com>
Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com>
2026-03-07 14:31:36 +01:00
marukai67
0d043d071e
signer/core: prevent nil pointer panics in keystore operations (#33829)
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
Add nil checks to prevent potential panics when keystore backend is
unavailable in the Clef signer API.
2026-03-06 21:50:30 +01:00
Guillaume Ballet
ecee64ecdc
core: fix TestProcessVerkle flaky test (#33971)
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
`GenerateChain` commits trie nodes asynchronously, and it can happen
that some nodes aren't making it to the db in time for `GenerateChain`
to open it and find the data it is looking for.
2026-03-06 19:03:05 +01:00
Guillaume Ballet
3f1871524f
trie/bintrie: cache hashes of clean nodes so as not to rehash the whole tree (#33961)
This is an optimization that existed for verkle and the MPT, but that
got dropped during the rebase.

Mark the nodes that were modified as needing recomputation, and skip the
hash computation if this is not needed. Otherwise, the whole tree is
hashed, which kills performance.
2026-03-06 18:06:24 +01:00
Guillaume Ballet
a0fb8102fe
trie/bintrie: fix overflow management in slot key computation (#33951)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Docker Image (push) Waiting to run
/ Windows Build (push) Waiting to run
The computation of `MAIN_STORAGE_OFFSET` was incorrect, causing the last
byte of the stem to be dropped. This means that there would be a
collision in the hash computation (at the preimage level, not a hash
collision of course) if two keys were only differing at byte 31.
2026-03-05 14:43:31 +01:00
Bosul Mun
344ce84a43
eth/fetcher: fix flaky test by improving event unsubscription (#33950)
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
Eth currently has a flaky test, related to the tx fetcher.

The issue seems to happen when Unsubscribe is called while sub is nil.
It seems that chain.Stop() may be invoked before the loop starts in some
tests, but the exact cause is still under investigation through repeated
runs. I think this change will at least prevent the error.
2026-03-05 11:48:44 +08:00
Sina M
ce64ab44ed
internal/ethapi: fix gas cap for eth_simulateV1 (#33952)
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 a regression in #33593 where a block gas limit > gasCap resulted
in more execution than the gas cap.
2026-03-05 09:09:07 +08:00
J
fc8c10476d
internal/ethapi: add MaxUsedGas field to eth_simulateV1 response (#32789)
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
closes #32741
2026-03-04 12:37:47 +01:00
Jonny Rhea
402c71f2e2
internal/telemetry: fix undersized span queue causing dropped spans (#33927)
The BatchSpanProcessor queue size was incorrectly set to
DefaultMaxExportBatchSize (512) instead of DefaultMaxQueueSize (2048).

I noticed the issue on bloatnet when analyzing the block building
traces. During a particular run, the miner was including 1000
transactions in a single block. When telemetry is enabled, the miner
creates a span for each transaction added to the block. With the queue
capped at 512, spans were silently dropped when production outpaced the
span export, resulting in incomplete traces with orphaned spans. While
this doesn't eliminate the possibility of drops under extreme
load, using the correct default restores the 4x buffer between queue
capacity and export batch size that the SDK was designed around.
2026-03-04 11:47:10 +01:00
Jonny Rhea
28dad943f6
cmd/geth: set default cache to 4096 (#33836)
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
Mainnet was already overriding --cache to 4096. This PR just makes this
the default.
2026-03-04 11:21:11 +01:00
Marius van der Wijden
6d0dd08860
core: implement eip-7778: block gas accounting without refunds (#33593)
Implements https://eips.ethereum.org/EIPS/eip-7778

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2026-03-04 18:18:18 +08: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
Jonny Rhea
814edc5308
core/vm: Switch to branchless normalization and extend EXCHANGE (#33869)
For bal-devnet-3 we need to update the EIP-8024 implementation to the
latest spec changes: https://github.com/ethereum/EIPs/pull/11306

> Note: I deleted tests not specified in the EIP bc maintaining them
through EIP changes is too error prone.
2026-03-04 10:34:27 +01:00
rjl493456442
6d99759f01
cmd, core, eth, tests: prevent state flushing in RPC (#33931)
Fixes https://github.com/ethereum/go-ethereum/issues/33572
2026-03-04 14:40:45 +08:00
DeFi Junkie
fe3a74e610
core/vm: use amsterdam jump table in lookup (#33947)
Return the Amsterdam instruction set from `LookupInstructionSet` when
`IsAmsterdam` is true, so Amsterdam rules no longer fall through to the
Osaka jump table.

---------

Co-authored-by: rjl493456442 <garyrong0905@gmail.com>
2026-03-04 13:42:25 +08:00
Jonny Rhea
4f75049ea0
miner: avoid unnecessary work after payload resolution (#33943)
In `buildPayload()`, the background goroutine uses a `select` to wait on
the recommit timer, the stop channel, and the end timer. When both
`timer.C` and `payload.stop` are ready simultaneously, Go's `select`
picks a case non-deterministically. This means the loop can enter the
`timer.C` case and perform an unnecessary `generateWork` call even after
the payload has been resolved.

Add a non-blocking check of `payload.stop` at the top of the `timer.C`
case to exit immediately when the payload has already been delivered.
2026-03-04 11:58:51 +08:00
Jonny Rhea
773f71bb9e
miner: enable trie prefetcher in block builder (#33945)
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-04 10:17:07 +08:00
Jonny Rhea
856e4d55d8
go.mod: bump go.opentelemetry.io/otel/sdk from 1.39.0 to 1.40.0 (#33946)
https://github.com/ethereum/go-ethereum/pull/33916 + cmd/keeper go mod
tidy

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-03 22:28:09 +01:00
Felix Lange
db7d3a4e0e version: begin v1.17.2 release cycle
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-03 13:49:09 +01:00
Felix Lange
16783c167c version: release go-ethereum v1.17.1 stable 2026-03-03 13:41:41 +01:00
Felix Lange
9962e2c9f3
p2p/tracker: fix crash in clean when tracker is stopped (#33940) 2026-03-03 12:54:24 +01:00
Sina M
d318e8eba9
node: disable http2 for auth API (#33922)
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
We got a report that after v1.17.0 a geth-teku node starts to time out
on engine_getBlobsV2 after around 3h of operation. The culprit seems to
be our optional http2 service which Teku attempts first. The exact cause
of the timeout is still unclear.

This PR is more of a workaround than proper fix until we figure out the
underlying issue. But I don't expect http2 to particularly benefit
engine API throughput and latency. Hence it should be fine to disable it
for now.
2026-03-03 00:02:44 +01:00
vickkkkkyy
b25080cac0
miner: account for generateWork elapsed time in payload rebuild timer (#33908)
The payload rebuild loop resets the timer with the full Recommit
duration after generateWork returns, making the actual interval
generateWork_elapsed + Recommit instead of Recommit alone.

Since fillTransactions uses Recommit (2s) as its timeout ceiling, the
effective rebuild interval can reach ~4s under heavy blob workloads —
only 1–2 rebuilds in a 6s half-slot window instead of the intended 3.

Fix by subtracting elapsed time from the timer reset.

### Before this fix

```
t=0s  timer fires, generateWork starts
t=2s  fillTransactions times out, timer.Reset(2s)
t=4s  second rebuild starts
t=6s  CL calls getPayload — gets the t=2s result (1 effective rebuild)
```

### After

```
t=0s  timer fires, generateWork starts
t=2s  fillTransactions times out, timer.Reset(2s - 2s = 0)
t=2s  second rebuild starts immediately
t=4s  timer.Reset(0), third rebuild starts
t=6s  CL calls getPayload — gets the t=4s result (3 effective rebuilds)
```
2026-03-03 00:01:55 +01:00
Csaba Kiraly
48cfc97776
core/txpool/blobpool: delay announcement of low fee txs (#33893)
This PR introduces a threshold (relative to current market base fees),
below which we suppress the diffusion of low fee transactions. Once base
fees go down, and if the transactions were not evicted in the meantime,
we release these transactions.

The PR also updates the bucketing logic to be more sensitive, removing
the extra logarithm. Blobpool description is also
updated to reflect the new behavior.

EIP-7918 changed the maximim blob fee decrease that can happen in a
slot. The PR also updates fee jump calculation to reflect this.

---------

Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
2026-03-02 23:59:33 +01:00
Csaba Kiraly
1eead2ec33
core/types: fix transaction pool price-heap comparison (#33923)
Fixes priceheap comparison in some edge cases.

---------

Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
2026-03-02 23:42:39 +01:00
jwasinger
2726c9ef9e
core/vm: enable 8024 instructions in Amsterdam (#33928) 2026-03-02 17:01:06 -05:00
Guillaume Ballet
5695fbc156
.github: set @gballet as codeowner for keeper (#33920)
Some checks are pending
/ Keeper Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
2026-03-02 06:43:21 -07:00
Guillaume Ballet
825436f043
AGENTS.md: add instruction not to commit binaries (#33921)
I noticed that some autonomous agents have a tendency to commit binaries
if asked to create a PR.
2026-03-02 06:42:38 -07:00
Bosul Mun
723aae2b4e
eth/protocols/eth: drop protocol version eth/68 (#33511)
Some checks failed
/ Keeper Build (push) Has been cancelled
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
With this, we are dropping support for protocol version eth/68. The only supported
version is eth/69 now. The p2p receipt encoding logic can be simplified a lot, and
processing of receipts during sync gets a little faster because we now transform
the network encoding into the database encoding directly, without decoding the
receipts first.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-02-28 21:43:40 +01:00
Delweng
cee751a1ed
eth: fix the flaky test of TestSnapSyncDisabling68 (#33896)
Some checks failed
/ Keeper Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Linux Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
fix the flaky test found in
https://ci.appveyor.com/project/ethereum/go-ethereum/builds/53601688/job/af5ccvufpm9usq39

1. increase the timeout from 3+1s to 15s, and use timer instead of
sleep(in the CI env, it may need more time to sync the 1024 blocks)
2. add `synced.Load()` to ensure the full async chain is finished

Signed-off-by: Delweng <delweng@gmail.com>
2026-02-27 12:51:01 +01:00
Guillaume Ballet
95c6b05806
trie/bintrie: fix endianness in code chunk key computation (#33900)
The endianness was wrong, which means that the code chunks were stored
in the wrong location in the tree.
2026-02-27 11:35:13 +01:00
Felix Lange
7793e00f0d
Dockerfile: upgrade to Go 1.26 (#33899)
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
We didn't upgrade to 1.25, so this jumps over one version. I want to
upgrade all builds to Go 1.26 soon, but let's start with the Docker
build to get a sense of any possible issues.
2026-02-26 21:18:00 +01:00
Marius van der Wijden
1b1133d669
go.mod: update ckzg (#33901) 2026-02-26 20:04:25 +01:00
rjl493456442
be92f5487e
trie: error out for unexpected key-value pairs preceding the range (#33898)
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-02-26 23:00:02 +08:00
Sina M
8a4345611d
build: update ubuntu distros list (#33864)
The`plucky` and `oracular` have reached end of life. That's why
launchpad isn't building them anymore:
https://launchpad.net/~ethereum/+archive/ubuntu/ethereum/+packages.
2026-02-26 13:55:53 +01:00
Marius van der Wijden
f811bfe4fd
core/vm: implement eip-7843: SLOTNUM (#33589)
Implements the slotnum opcode as specified here:
https://eips.ethereum.org/EIPS/eip-7843
2026-02-26 13:53:46 +01:00
Guillaume Ballet
406a852ec8
AGENTS.md: add AGENTS.md (#33890)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
Co-authored-by: tellabg <249254436+tellabg@users.noreply.github.com>
Co-authored-by: lightclient <lightclient@protonmail.com>
2026-02-24 23:08:23 -07:00
ANtutov
2a45272408
eth/protocols/eth: fix handshake timeout metrics classification (#33539)
Previously, handshake timeouts were recorded as generic peer errors
instead of timeout errors. waitForHandshake passed a raw
p2p.DiscReadTimeout into markError, but markError classified errors only
via errors.Unwrap(err), which returns nil for non-wrapped errors. As a
result, the timeoutError meter was never incremented and all such
failures fell into the peerError bucket.

This change makes markError switch on the base error, using
errors.Unwrap(err) when available and falling back to the original error
otherwise. With this adjustment, p2p.DiscReadTimeout is correctly mapped
to timeoutError, while existing behaviour for the other wrapped sentinel
errors remains unchanged

---------

Co-authored-by: lightclient <lightclient@protonmail.com>
2026-02-24 21:50:26 -07:00
Fynn
8450e40798
cmd/geth: add inspect trie tool to analysis trie storage (#28892)
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 adds a tool names `inpsect-trie`, aimed to analyze the mpt and
its node storage more efficiently.

## Example
 ./geth db inspect-trie --datadir server/data-seed/ latest 4000

## Result

- MPT shape
- Account Trie 
- Top N Storage Trie
```
+-------+-------+--------------+-------------+--------------+
|   -   | LEVEL | SHORTNODECNT | FULLNODECNT | VALUENODECNT |
+-------+-------+--------------+-------------+--------------+
|   -   |   0   |      0       |      1      |      0       |
|   -   |   1   |      0       |     16      |      0       |
|   -   |   2   |      76      |     32      |      74      |
|   -   |   3   |      66      |      1      |      66      |
|   -   |   4   |      2       |      0      |      2       |
| Total |  144  |      50      |     142     |
+-------+-------+--------------+-------------+--------------+
AccountTrie
+-------+-------+--------------+-------------+--------------+
|   -   | LEVEL | SHORTNODECNT | FULLNODECNT | VALUENODECNT |
+-------+-------+--------------+-------------+--------------+
|   -   |   0   |      0       |      1      |      0       |
|   -   |   1   |      0       |     16      |      0       |
|   -   |   2   |     108      |     84      |     104      |
|   -   |   3   |     195      |      5      |     195      |
|   -   |   4   |      10      |      0      |      10      |
| Total |  313  |     106      |     309     |
+-------+-------+--------------+-------------+--------------+
ContractTrie-0xc874e65ccffb133d9db4ff637e62532ef6ecef3223845d02f522c55786782911
+-------+-------+--------------+-------------+--------------+
|   -   | LEVEL | SHORTNODECNT | FULLNODECNT | VALUENODECNT |
+-------+-------+--------------+-------------+--------------+
|   -   |   0   |      0       |      1      |      0       |
|   -   |   1   |      0       |     16      |      0       |
|   -   |   2   |      57      |     14      |      56      |
|   -   |   3   |      33      |      0      |      33      |
| Total |  90   |      31      |     89      |
+-------+-------+--------------+-------------+--------------+
ContractTrie-0x1d7dcb6a0ce5227c5379fc5b0e004561d7833b063355f69bfea3178f08fbaab4
+-------+-------+--------------+-------------+--------------+
|   -   | LEVEL | SHORTNODECNT | FULLNODECNT | VALUENODECNT |
+-------+-------+--------------+-------------+--------------+
|   -   |   0   |      0       |      1      |      0       |
|   -   |   1   |      5       |      8      |      5       |
|   -   |   2   |      16      |      1      |      16      |
|   -   |   3   |      2       |      0      |      2       |
| Total |  23   |      10      |     23      |
+-------+-------+--------------+-------------+--------------+
ContractTrie-0xaa8a4783ebbb3bec45d3e804b3c59bfd486edfa39cbeda1d42bf86c08a0ebc0f
+-------+-------+--------------+-------------+--------------+
|   -   | LEVEL | SHORTNODECNT | FULLNODECNT | VALUENODECNT |
+-------+-------+--------------+-------------+--------------+
|   -   |   0   |      0       |      1      |      0       |
|   -   |   1   |      9       |      3      |      9       |
|   -   |   2   |      7       |      1      |      7       |
|   -   |   3   |      2       |      0      |      2       |
| Total |  18   |      5       |     18      |
+-------+-------+--------------+-------------+--------------+
ContractTrie-0x9d2804d0562391d7cfcfaf0013f0352e176a94403a58577ebf82168a21514441
+-------+-------+--------------+-------------+--------------+
|   -   | LEVEL | SHORTNODECNT | FULLNODECNT | VALUENODECNT |
+-------+-------+--------------+-------------+--------------+
|   -   |   0   |      0       |      1      |      0       |
|   -   |   1   |      6       |      4      |      6       |
|   -   |   2   |      8       |      0      |      8       |
| Total |  14   |      5       |     14      |
+-------+-------+--------------+-------------+--------------+
ContractTrie-0x17e3eb95d0e6e92b42c0b3e95c6e75080c9fcd83e706344712e9587375de96e1
+-------+-------+--------------+-------------+--------------+
|   -   | LEVEL | SHORTNODECNT | FULLNODECNT | VALUENODECNT |
+-------+-------+--------------+-------------+--------------+
|   -   |   0   |      0       |      1      |      0       |
|   -   |   1   |      5       |      3      |      5       |
|   -   |   2   |      7       |      0      |      7       |
| Total |  12   |      4       |     12      |
+-------+-------+--------------+-------------+--------------+
ContractTrie-0xc017ca90c8aa37693c38f80436bb15bde46d7b30a503aa808cb7814127468a44
Contract Trie, total trie num: 142, ShortNodeCnt: 620, FullNodeCnt: 204, ValueNodeCnt: 615
```

---------

Co-authored-by: lightclient <lightclient@protonmail.com>
Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
2026-02-24 10:56:00 -07:00
cui
9ecb6c4ae6
core: reduce alloc (#33576)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
inside tx.GasPrice()/GasFeeCap()/GasTipCap() already new a big.Int.  
bench result:  
```
goos: darwin
goarch: arm64
pkg: github.com/ethereum/go-ethereum/core
cpu: Apple M4
                        │   old.txt   │               new.txt               │
                        │   sec/op    │   sec/op     vs base                │
TransactionToMessage-10   240.1n ± 7%   175.1n ± 7%  -27.09% (p=0.000 n=10)

                        │  old.txt   │              new.txt               │
                        │    B/op    │    B/op     vs base                │
TransactionToMessage-10   544.0 ± 0%   424.0 ± 0%  -22.06% (p=0.000 n=10)

                        │  old.txt   │              new.txt               │
                        │ allocs/op  │ allocs/op   vs base                │
TransactionToMessage-10   17.00 ± 0%   11.00 ± 0%  -35.29% (p=0.000 n=10)
```
benchmark code:  

```
// Copyright 2025 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package core

import (
	"math/big"
	"testing"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/params"
)

// BenchmarkTransactionToMessage benchmarks the TransactionToMessage function.
func BenchmarkTransactionToMessage(b *testing.B) {
	key, _ := crypto.GenerateKey()
	signer := types.LatestSigner(params.TestChainConfig)
	to := common.HexToAddress("0x000000000000000000000000000000000000dead")
	
	// Create a DynamicFeeTx transaction
	txdata := &types.DynamicFeeTx{
		ChainID:   big.NewInt(1),
		Nonce:     42,
		GasTipCap: big.NewInt(1000000000),  // 1 gwei
		GasFeeCap: big.NewInt(2000000000),  // 2 gwei
		Gas:       21000,
		To:        &to,
		Value:     big.NewInt(1000000000000000000), // 1 ether
		Data:      []byte{0x12, 0x34, 0x56, 0x78},
		AccessList: types.AccessList{
			types.AccessTuple{
				Address:     common.HexToAddress("0x0000000000000000000000000000000000000001"),
				StorageKeys: []common.Hash{
					common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"),
				},
			},
		},
	}
	tx, _ := types.SignNewTx(key, signer, txdata)
	baseFee := big.NewInt(1500000000) // 1.5 gwei

	b.ResetTimer()
	b.ReportAllocs()
	for i := 0; i < b.N; i++ {
		_, err := TransactionToMessage(tx, signer, baseFee)
		if err != nil {
			b.Fatal(err)
		}
	}
}
l
```
2026-02-24 07:40:01 -07: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
rjl493456442
cbf3d8fed2
core/vm: touch precompile object with Amsterdam enabled (#33742)
https://eips.ethereum.org/EIPS/eip-7928 spec:

> Precompiled contracts: Precompiles MUST be included when accessed. 
   If a precompile receives value, it is recorded with a balance change.
   Otherwise, it is included with empty change lists.

The precompiled contracts are not explicitly touched when they are
invoked since Amsterdam fork.
2026-02-24 21:55:10 +08:00
rjl493456442
199ac16e07
core/types/bal: change code change type to list (#33774)
To align with the latest spec of EIP-7928:

```
# CodeChange: [block_access_index, new_code]
CodeChange = [BlockAccessIndex, Bytecode]
```
2026-02-24 21:53:20 +08:00
IONode Online
01083736c8
core/txpool/blobpool: remove unused adds slice in Add() (#33887) 2026-02-24 20:24:16 +08:00
Csaba Kiraly
59ad40e562
eth: check for tx on chain as well (#33607)
The fetcher should not fetch transactions that are already on chain.
Until now we were only checking in the txpool, but that does not have
the old transaction. This was leading to extra fetches of transactions
that were announced by a peer but are already on chain.

Here we extend the check to the chain as well.
2026-02-24 11:21:03 +01:00
CPerezz
c2e1785a48
eth/protocols/snap: restore peers to idle pool on request revert (#33790)
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
All five `revert*Request` functions (account, bytecode, storage,
trienode heal, bytecode heal) remove the request from the tracked set
but never restore the peer to its corresponding idle pool. When a
request times out and no response arrives, the peer is permanently lost
from the idle pool, preventing new work from being assigned to it.

In normal operation mode (snap-sync full state) this bug is masked by
pivot movement (which resets idle pools via new Sync() cycles every ~15
minutes) and peer churn (reconnections re-add peers via Register()).
However in scenarios like the one I have running my (partial-stateful
node)[https://github.com/ethereum/go-ethereum/pull/33764] with
long-running sync cycles and few peers, all peers can eventually leak
out of the idle pools, stalling sync entirely.

Fix: after deleting from the request map, restore the peer to its idle
pool if it is still registered (guards against the peer-drop path where
Unregister already removed the peer). This mirrors the pattern used in
all five On* response handlers.


This only seems to manifest in peer-thirstly scenarios as where I find
myself when testing snapsync for the partial-statefull node).
Still, thought was at least good to raise this point. Unsure if required
to discuss or not
2026-02-24 09:14:11 +08:00
Nakanishi Hiro
82fad31540
internal/ethapi: add eth_getStorageValues method (#32591)
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
Implements the new eth_getStorageValues method. It returns storage
values for a list of contracts.

Spec: https://github.com/ethereum/execution-apis/pull/756

---------

Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2026-02-23 20:47:30 +01:00
vickkkkkyy
1625064c68
internal/ethapi: include AuthorizationList in gas estimation (#33849)
Fixes an issue where AuthorizationList wasn't copied over when
estimating gas for a user-provided transaction.
2026-02-23 18:07:26 +01:00
Marius van der Wijden
1d1a094d51
beacon/blsync: ignore beacon syncer reorging errors (#33628)
Downgrades beacon syncer reorging from Error to Debug
closes https://github.com/ethereum/go-ethereum/issues/29916
2026-02-23 16:02:23 +01:00
Marius van der Wijden
e40aa46e88
eth/catalyst: implement testing_buildBlockV1 (#33656)
implements
https://github.com/ethereum/execution-apis/pull/710/changes#r2712256529

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-02-23 15:56:31 +01:00
Csaba Kiraly
d3dd48e59d
metrics: allow changing influxdb interval (#33767)
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
The PR exposes the InfuxDB reporting interval as a CLI parameter, which
was previously fixed 10s. Default is still kept at 10s.
Note that decreasing the interval comes with notable extra traffic and
load on InfluxDB.
2026-02-23 14:27:25 +01:00
Felix Lange
00cbd2e6f4
p2p/discover/v5wire: use Whoareyou.ChallengeData instead of storing encoded packet (#31547)
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 changes the challenge resend logic again to use the existing
`ChallengeData` field of `v5wire.Whoareyou` instead of storing a second
copy of the packet in `Whoareyou.Encoded`. It's more correct this way
since `ChallengeData` is supposed to be the data that is used by the ID
verification procedure.

Also adapts the cross-client test to verify this behavior.

Follow-up to #31543
2026-02-22 21:58:47 +01:00
Felix Lange
453d0f9299
build: upgrade to golangci-lint v2.10.1 (#33875)
Some checks are pending
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Linux Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run
2026-02-21 20:53:02 +01:00
Felix Lange
6d865ccd30
build: upgrade -dlgo version to 1.25.7 (#33874) 2026-02-21 20:52:43 +01:00
rjl493456442
54f72c796f
core/rawdb: revert "check pruning tail in HasBody and HasReceipts" (#33865)
Some checks failed
/ Linux Build (push) Has been cancelled
/ Linux Build (arm) (push) Has been cancelled
/ Keeper Build (push) Has been cancelled
/ Windows Build (push) Has been cancelled
/ Docker Image (push) Has been cancelled
Reverts ethereum/go-ethereum#33747.

This change suffers an unexpected issue during the sync with
`history.chain=postmerge`.
2026-02-19 11:43:44 +01:00
Sina M
2a62df3815
.github: fix actions 32bit test (#33866)
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-02-18 18:28:53 +01:00
rjl493456442
01fe1d716c
core/vm: disable the value transfer in syscall (#33741)
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
In src/ethereum/forks/amsterdam/vm/interpreter.py:299-304, the caller
address is
only tracked for block level accessList when there's a value transfer:

```python
if message.should_transfer_value and message.value != 0:  
    # Track value transfer  
    sender_balance = get_account(state, message.caller).balance  
    recipient_balance = get_account(state, message.current_target).balance  

    track_address(message.state_changes, message.caller)  # Line 304
```

Since system transactions have should_transfer_value=False and value=0, 
this condition is never met, so the caller (SYSTEM_ADDRESS) is not
tracked.

This condition is applied for the syscall in the geth implementation,
aligning with the spec of EIP7928.

---------

Co-authored-by: Felix Lange <fjl@twurst.com>
2026-02-18 08:40:23 +08:00
spencer
3eed0580d4
cmd/evm: add --opcode.count flag to t8n (#33800)
Adds `--opcode.count=<file>` flag to `evm t8n` that writes per-opcode
execution frequency counts to a JSON file (relative to
`--output.basedir`).

---------

Co-authored-by: MariusVanDerWijden <m.vanderwijden@live.de>
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
2026-02-17 20:42:53 +01:00
Felix Lange
1054276906 version: begin v1.17.1 release cycle
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-02-17 17:17:00 +01:00
747 changed files with 68594 additions and 29888 deletions

View file

@ -145,7 +145,7 @@ jobs:
windows: windows:
name: Windows Build name: Windows Build
runs-on: "win-11" runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -155,24 +155,49 @@ jobs:
go-version: 1.24 go-version: 1.24
cache: false cache: false
# Note: gcc.exe only works properly if the corresponding bin/ directory is - name: Install cross toolchain
# contained in PATH. run: |
apt-get update
apt-get -yq --no-install-suggests --no-install-recommends install \
gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 nsis
- name: "Build (amd64)" - name: "Build (amd64)"
shell: cmd
run: | run: |
set PATH=%GETH_MINGW%\bin;%PATH% go run build/ci.go install -dlgo -os windows -arch amd64 -cc x86_64-w64-mingw32-gcc
go run build/ci.go install -dlgo -arch amd64 -cc %GETH_MINGW%\bin\gcc.exe
- name: "Create/upload archive (amd64)"
run: |
go run build/ci.go archive -os windows -arch amd64 -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
env: env:
GETH_MINGW: 'C:\msys64\mingw64' WINDOWS_SIGNING_KEY: ${{ secrets.WINDOWS_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: "Create/upload NSIS installer (amd64)"
run: |
go run build/ci.go nsis -arch amd64 -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
rm -f build/bin/*
env:
WINDOWS_SIGNING_KEY: ${{ secrets.WINDOWS_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: "Build (386)" - name: "Build (386)"
shell: cmd
run: | run: |
set PATH=%GETH_MINGW%\bin;%PATH% go run build/ci.go install -dlgo -os windows -arch 386 -cc i686-w64-mingw32-gcc
go run build/ci.go install -dlgo -arch 386 -cc %GETH_MINGW%\bin\gcc.exe
- name: "Create/upload archive (386)"
run: |
go run build/ci.go archive -os windows -arch 386 -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
env: env:
GETH_MINGW: 'C:\msys64\mingw32' WINDOWS_SIGNING_KEY: ${{ secrets.WINDOWS_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
- name: "Create/upload NSIS installer (386)"
run: |
go run build/ci.go nsis -arch 386 -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
rm -f build/bin/*
env:
WINDOWS_SIGNING_KEY: ${{ secrets.WINDOWS_SIGNING_KEY }}
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
docker: docker:
name: Docker Image name: Docker Image

6
.github/CODEOWNERS vendored
View file

@ -10,20 +10,18 @@ beacon/merkle/ @zsfelfoldi
beacon/types/ @zsfelfoldi @fjl beacon/types/ @zsfelfoldi @fjl
beacon/params/ @zsfelfoldi @fjl beacon/params/ @zsfelfoldi @fjl
cmd/evm/ @MariusVanDerWijden @lightclient cmd/evm/ @MariusVanDerWijden @lightclient
cmd/keeper/ @gballet
core/state/ @rjl493456442 core/state/ @rjl493456442
crypto/ @gballet @jwasinger @fjl crypto/ @gballet @jwasinger @fjl
core/ @rjl493456442 core/ @rjl493456442
eth/ @rjl493456442 eth/ @rjl493456442
eth/catalyst/ @MariusVanDerWijden @lightclient @fjl @jwasinger eth/catalyst/ @MariusVanDerWijden @lightclient @fjl @jwasinger
eth/tracers/ @s1na
ethclient/ @fjl ethclient/ @fjl
ethdb/ @rjl493456442 ethdb/ @rjl493456442
event/ @fjl event/ @fjl
trie/ @rjl493456442 @gballet trie/ @rjl493456442 @gballet
triedb/ @rjl493456442 triedb/ @rjl493456442
core/tracing/ @s1na internal/ethapi/ @fjl @lightclient
graphql/ @s1na
internal/ethapi/ @fjl @s1na @lightclient
internal/era/ @lightclient internal/era/ @lightclient
miner/ @MariusVanDerWijden @fjl @rjl493456442 miner/ @MariusVanDerWijden @fjl @rjl493456442
node/ @fjl node/ @fjl

29
.github/workflows/freebsd.yml vendored Normal file
View file

@ -0,0 +1,29 @@
on:
push:
branches:
- freebsd-github-action
workflow_dispatch:
jobs:
build:
name: FreeBSD-build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
submodules: false
- name: Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v1
with:
release: "15.0"
usesh: true
prepare: |
pkg install -y go
run: |
freebsd-version
uname -a
go version
go run ./build/ci.go test -p 8

View file

@ -7,6 +7,11 @@ on:
- master - master
workflow_dispatch: workflow_dispatch:
# Free runner capacity by cancelling superseded PR runs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs: jobs:
lint: lint:
name: Lint name: Lint
@ -69,8 +74,8 @@ jobs:
- name: Install cross toolchain - name: Install cross toolchain
run: | run: |
apt-get update sudo apt-get update
apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib sudo apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
- name: Build - name: Build
run: go run build/ci.go test -arch 386 -short -p 8 run: go run build/ci.go test -arch 386 -short -p 8
@ -97,3 +102,44 @@ jobs:
- name: Run tests - name: Run tests
run: go run build/ci.go test -p 8 run: go run build/ci.go test -p 8
windows:
name: Windows ${{ matrix.arch }}
needs: lint
runs-on: [self-hosted, windows, x64]
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
mingw: 'C:\msys64\mingw64'
test: true
- arch: '386'
mingw: 'C:\msys64\mingw32'
test: false
env:
GETH_MINGW: ${{ matrix.mingw }}
GETH_CC: ${{ matrix.mingw }}\bin\gcc.exe
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
cache: false
- name: Build
shell: cmd
run: |
set PATH=%GETH_MINGW%\bin;%PATH%
go run build/ci.go install -arch ${{ matrix.arch }} -cc %GETH_CC%
- name: Run tests
if: matrix.test
shell: cmd
run: |
set PATH=%GETH_MINGW%\bin;%PATH%
go run build/ci.go test -arch ${{ matrix.arch }} -cc %GETH_CC% -short -p 8

View file

@ -48,6 +48,9 @@ Bas van Kervel <bas@ethdev.com> <bas-vk@users.noreply.github.com>
Boqin Qin <bobbqqin@bupt.edu.cn> Boqin Qin <bobbqqin@bupt.edu.cn>
Boqin Qin <bobbqqin@bupt.edu.cn> <Bobbqqin@gmail.com> Boqin Qin <bobbqqin@bupt.edu.cn> <Bobbqqin@gmail.com>
Bosul Mun <bsbs8645@snu.ac.kr>
Bosul Mun <bsbs8645@snu.ac.kr> <bosul.mun@ethereum.org>
Casey Detrio <cdetrio@gmail.com> Casey Detrio <cdetrio@gmail.com>
Charlotte <tqpcharlie@proton.me> Charlotte <tqpcharlie@proton.me>

102
AGENTS.md Normal file
View file

@ -0,0 +1,102 @@
# AGENTS
## Guidelines
- **Keep changes minimal and focused.** Only modify code directly related to the task at hand. Do not refactor unrelated code, rename existing variables or functions for style, or bundle unrelated fixes into the same commit or PR.
- **Do not add, remove, or update dependencies** unless the task explicitly requires it.
## Pre-Commit Checklist
Before every commit, run **all** of the following checks and ensure they pass:
### 1. Formatting
Before committing, always run `gofmt` and `goimports` on all modified files:
```sh
gofmt -w <modified files>
goimports -w <modified files>
```
### 2. Build All Commands
Verify that all tools compile successfully:
```sh
make all
```
This builds all executables under `cmd/`, including `keeper` which has special build requirements.
### 3. Tests
While iterating during development, use `-short` for faster feedback:
```sh
go run ./build/ci.go test -short
```
Before committing, run the full test suite **without** `-short` to ensure all tests pass, including the Ethereum execution-spec tests and all state/block test permutations:
```sh
go run ./build/ci.go test
```
### 4. Linting
```sh
go run ./build/ci.go lint
```
This runs additional style checks. Fix any issues before committing.
### 5. Generated Code
```sh
go run ./build/ci.go check_generate
```
Ensures that all generated files (e.g., `gen_*.go`) are up to date. If this fails, first install the required code generators by running `make devtools`, then run the appropriate `go generate` commands and include the updated files in your commit.
### 6. Dependency Hygiene
```sh
go run ./build/ci.go check_baddeps
```
Verifies that no forbidden dependencies have been introduced.
## What to include in commits
Do not commit binaries, whether they are produced by the main build or byproducts of investigations.
## Commit Message Format
Commit messages must be prefixed with the package(s) they modify, followed by a short lowercase description:
```
<package(s)>: description
```
Examples:
- `core/vm: fix stack overflow in PUSH instruction`
- `eth, rpc: make trace configs optional`
- `cmd/geth: add new flag for sync mode`
Use comma-separated package names when multiple areas are affected. Keep the description concise.
## Pull Request Title Format
PR titles follow the same convention as commit messages:
```
<list of modified paths>: description
```
Examples:
- `core/vm: fix stack overflow in PUSH instruction`
- `core, eth: add arena allocator support`
- `cmd/geth, internal/ethapi: refactor transaction args`
- `trie/archiver: streaming subtree archival to fix OOM`
Use the top-level package paths, comma-separated if multiple areas are affected. Only mention the directories with functional changes, interface changes that trickle all over the codebase should not generate an exhaustive list. The description should be a short, lowercase summary of the change.

View file

@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM="" ARG BUILDNUM=""
# Build Geth in a stock Go builder container # Build Geth in a stock Go builder container
FROM golang:1.24-alpine AS builder FROM golang:1.26-alpine AS builder
RUN apk add --no-cache gcc musl-dev linux-headers git RUN apk add --no-cache gcc musl-dev linux-headers git

View file

@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM="" ARG BUILDNUM=""
# Build Geth in a stock Go builder container # Build Geth in a stock Go builder container
FROM golang:1.24-alpine AS builder FROM golang:1.26-alpine AS builder
RUN apk add --no-cache gcc musl-dev linux-headers git RUN apk add --no-cache gcc musl-dev linux-headers git

View file

@ -38,7 +38,6 @@ directory.
| Command | Description | | Command | Description |
| :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/fundamentals/command-line-options) for command line options. | | **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/fundamentals/command-line-options) for command line options. |
| `clef` | Stand-alone signing tool, which can be used as a backend signer for `geth`. |
| `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. | | `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. |
| `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings) page for details. | | `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings) page for details. |
| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). | | `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). |

View file

@ -11,7 +11,6 @@ Audit reports are published in the `docs` folder: https://github.com/ethereum/go
| Scope | Date | Report Link | | Scope | Date | Report Link |
| ------- | ------- | ----------- | | ------- | ------- | ----------- |
| `geth` | 20170425 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2017-04-25_Geth-audit_Truesec.pdf) | | `geth` | 20170425 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2017-04-25_Geth-audit_Truesec.pdf) |
| `clef` | 20180914 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2018-09-14_Clef-audit_NCC.pdf) |
| `Discv5` | 20191015 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2019-10-15_Discv5_audit_LeastAuthority.pdf) | | `Discv5` | 20191015 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2019-10-15_Discv5_audit_LeastAuthority.pdf) |
| `Discv5` | 20200124 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2020-01-24_DiscV5_audit_Cure53.pdf) | | `Discv5` | 20200124 | [pdf](https://github.com/ethereum/go-ethereum/blob/master/docs/audits/2020-01-24_DiscV5_audit_Cure53.pdf) |

View file

@ -4,8 +4,10 @@
package {{.Package}} package {{.Package}}
import ( import (
"context"
"math/big" "math/big"
"strings" "strings"
"time"
"errors" "errors"
ethereum "github.com/ethereum/go-ethereum" ethereum "github.com/ethereum/go-ethereum"
@ -27,6 +29,8 @@ var (
_ = types.BloomLookup _ = types.BloomLookup
_ = event.NewSubscription _ = event.NewSubscription
_ = abi.ConvertType _ = abi.ConvertType
_ = time.Tick
_ = context.Background
) )
{{$structs := .Structs}} {{$structs := .Structs}}
@ -77,7 +81,11 @@ var (
return common.Address{}, nil, nil, errors.New("GetABI returned nil") return common.Address{}, nil, nil, errors.New("GetABI returned nil")
} }
{{range $pattern, $name := .Libraries}} {{range $pattern, $name := .Libraries}}
{{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend) {{decapitalise $name}}Addr, tx, _, _ := Deploy{{capitalise $name}}(auth, backend)
ctx, _ := context.WithTimeout(context.Background(), 5 * time.Second)
if err := bind.WaitAccepted(ctx, backend, tx); err != nil {
return common.Address{}, nil, nil, err
}
{{$contract.Type}}Bin = strings.ReplaceAll({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:]) {{$contract.Type}}Bin = strings.ReplaceAll({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:])
{{end}} {{end}}
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}}) address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})

View file

@ -59,6 +59,11 @@ var (
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *{{.Type}}) GetABI() abi.ABI {
return c.abi
}
// New{{.Type}} creates a new instance of {{.Type}}. // New{{.Type}} creates a new instance of {{.Type}}.
func New{{.Type}}() *{{.Type}} { func New{{.Type}}() *{{.Type}} {
parsed, err := {{.Type}}MetaData.ParseABI() parsed, err := {{.Type}}MetaData.ParseABI()
@ -183,8 +188,11 @@ var (
// Solidity: {{.Original.String}} // Solidity: {{.Original.String}}
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Unpack{{.Normalized.Name}}Event(log *types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) { func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Unpack{{.Normalized.Name}}Event(log *types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
event := "{{.Original.Name}}" event := "{{.Original.Name}}"
if len(log.Topics) == 0 || log.Topics[0] != {{ decapitalise $contract.Type}}.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != {{ decapitalise $contract.Type}}.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new({{$contract.Type}}{{.Normalized.Name}}) out := new({{$contract.Type}}{{.Normalized.Name}})
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -36,6 +36,11 @@ type CallbackParam struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *CallbackParam) GetABI() abi.ABI {
return c.abi
}
// NewCallbackParam creates a new instance of CallbackParam. // NewCallbackParam creates a new instance of CallbackParam.
func NewCallbackParam() *CallbackParam { func NewCallbackParam() *CallbackParam {
parsed, err := CallbackParamMetaData.ParseABI() parsed, err := CallbackParamMetaData.ParseABI()

View file

@ -36,6 +36,11 @@ type Crowdsale struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Crowdsale) GetABI() abi.ABI {
return c.abi
}
// NewCrowdsale creates a new instance of Crowdsale. // NewCrowdsale creates a new instance of Crowdsale.
func NewCrowdsale() *Crowdsale { func NewCrowdsale() *Crowdsale {
parsed, err := CrowdsaleMetaData.ParseABI() parsed, err := CrowdsaleMetaData.ParseABI()
@ -360,8 +365,11 @@ func (CrowdsaleFundTransfer) ContractEventName() string {
// Solidity: event FundTransfer(address backer, uint256 amount, bool isContribution) // Solidity: event FundTransfer(address backer, uint256 amount, bool isContribution)
func (crowdsale *Crowdsale) UnpackFundTransferEvent(log *types.Log) (*CrowdsaleFundTransfer, error) { func (crowdsale *Crowdsale) UnpackFundTransferEvent(log *types.Log) (*CrowdsaleFundTransfer, error) {
event := "FundTransfer" event := "FundTransfer"
if len(log.Topics) == 0 || log.Topics[0] != crowdsale.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != crowdsale.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(CrowdsaleFundTransfer) out := new(CrowdsaleFundTransfer)
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -36,6 +36,11 @@ type DAO struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *DAO) GetABI() abi.ABI {
return c.abi
}
// NewDAO creates a new instance of DAO. // NewDAO creates a new instance of DAO.
func NewDAO() *DAO { func NewDAO() *DAO {
parsed, err := DAOMetaData.ParseABI() parsed, err := DAOMetaData.ParseABI()
@ -606,8 +611,11 @@ func (DAOChangeOfRules) ContractEventName() string {
// Solidity: event ChangeOfRules(uint256 minimumQuorum, uint256 debatingPeriodInMinutes, int256 majorityMargin) // Solidity: event ChangeOfRules(uint256 minimumQuorum, uint256 debatingPeriodInMinutes, int256 majorityMargin)
func (dAO *DAO) UnpackChangeOfRulesEvent(log *types.Log) (*DAOChangeOfRules, error) { func (dAO *DAO) UnpackChangeOfRulesEvent(log *types.Log) (*DAOChangeOfRules, error) {
event := "ChangeOfRules" event := "ChangeOfRules"
if len(log.Topics) == 0 || log.Topics[0] != dAO.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != dAO.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(DAOChangeOfRules) out := new(DAOChangeOfRules)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -648,8 +656,11 @@ func (DAOMembershipChanged) ContractEventName() string {
// Solidity: event MembershipChanged(address member, bool isMember) // Solidity: event MembershipChanged(address member, bool isMember)
func (dAO *DAO) UnpackMembershipChangedEvent(log *types.Log) (*DAOMembershipChanged, error) { func (dAO *DAO) UnpackMembershipChangedEvent(log *types.Log) (*DAOMembershipChanged, error) {
event := "MembershipChanged" event := "MembershipChanged"
if len(log.Topics) == 0 || log.Topics[0] != dAO.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != dAO.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(DAOMembershipChanged) out := new(DAOMembershipChanged)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -692,8 +703,11 @@ func (DAOProposalAdded) ContractEventName() string {
// Solidity: event ProposalAdded(uint256 proposalID, address recipient, uint256 amount, string description) // Solidity: event ProposalAdded(uint256 proposalID, address recipient, uint256 amount, string description)
func (dAO *DAO) UnpackProposalAddedEvent(log *types.Log) (*DAOProposalAdded, error) { func (dAO *DAO) UnpackProposalAddedEvent(log *types.Log) (*DAOProposalAdded, error) {
event := "ProposalAdded" event := "ProposalAdded"
if len(log.Topics) == 0 || log.Topics[0] != dAO.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != dAO.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(DAOProposalAdded) out := new(DAOProposalAdded)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -736,8 +750,11 @@ func (DAOProposalTallied) ContractEventName() string {
// Solidity: event ProposalTallied(uint256 proposalID, int256 result, uint256 quorum, bool active) // Solidity: event ProposalTallied(uint256 proposalID, int256 result, uint256 quorum, bool active)
func (dAO *DAO) UnpackProposalTalliedEvent(log *types.Log) (*DAOProposalTallied, error) { func (dAO *DAO) UnpackProposalTalliedEvent(log *types.Log) (*DAOProposalTallied, error) {
event := "ProposalTallied" event := "ProposalTallied"
if len(log.Topics) == 0 || log.Topics[0] != dAO.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != dAO.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(DAOProposalTallied) out := new(DAOProposalTallied)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -780,8 +797,11 @@ func (DAOVoted) ContractEventName() string {
// Solidity: event Voted(uint256 proposalID, bool position, address voter, string justification) // Solidity: event Voted(uint256 proposalID, bool position, address voter, string justification)
func (dAO *DAO) UnpackVotedEvent(log *types.Log) (*DAOVoted, error) { func (dAO *DAO) UnpackVotedEvent(log *types.Log) (*DAOVoted, error) {
event := "Voted" event := "Voted"
if len(log.Topics) == 0 || log.Topics[0] != dAO.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != dAO.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(DAOVoted) out := new(DAOVoted)
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -36,6 +36,11 @@ type DeeplyNestedArray struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *DeeplyNestedArray) GetABI() abi.ABI {
return c.abi
}
// NewDeeplyNestedArray creates a new instance of DeeplyNestedArray. // NewDeeplyNestedArray creates a new instance of DeeplyNestedArray.
func NewDeeplyNestedArray() *DeeplyNestedArray { func NewDeeplyNestedArray() *DeeplyNestedArray {
parsed, err := DeeplyNestedArrayMetaData.ParseABI() parsed, err := DeeplyNestedArrayMetaData.ParseABI()

View file

@ -36,6 +36,11 @@ type Empty struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Empty) GetABI() abi.ABI {
return c.abi
}
// NewEmpty creates a new instance of Empty. // NewEmpty creates a new instance of Empty.
func NewEmpty() *Empty { func NewEmpty() *Empty {
parsed, err := EmptyMetaData.ParseABI() parsed, err := EmptyMetaData.ParseABI()

View file

@ -35,6 +35,11 @@ type EventChecker struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *EventChecker) GetABI() abi.ABI {
return c.abi
}
// NewEventChecker creates a new instance of EventChecker. // NewEventChecker creates a new instance of EventChecker.
func NewEventChecker() *EventChecker { func NewEventChecker() *EventChecker {
parsed, err := EventCheckerMetaData.ParseABI() parsed, err := EventCheckerMetaData.ParseABI()
@ -72,8 +77,11 @@ func (EventCheckerDynamic) ContractEventName() string {
// Solidity: event dynamic(string indexed idxStr, bytes indexed idxDat, string str, bytes dat) // Solidity: event dynamic(string indexed idxStr, bytes indexed idxDat, string str, bytes dat)
func (eventChecker *EventChecker) UnpackDynamicEvent(log *types.Log) (*EventCheckerDynamic, error) { func (eventChecker *EventChecker) UnpackDynamicEvent(log *types.Log) (*EventCheckerDynamic, error) {
event := "dynamic" event := "dynamic"
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != eventChecker.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(EventCheckerDynamic) out := new(EventCheckerDynamic)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -112,8 +120,11 @@ func (EventCheckerEmpty) ContractEventName() string {
// Solidity: event empty() // Solidity: event empty()
func (eventChecker *EventChecker) UnpackEmptyEvent(log *types.Log) (*EventCheckerEmpty, error) { func (eventChecker *EventChecker) UnpackEmptyEvent(log *types.Log) (*EventCheckerEmpty, error) {
event := "empty" event := "empty"
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != eventChecker.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(EventCheckerEmpty) out := new(EventCheckerEmpty)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -154,8 +165,11 @@ func (EventCheckerIndexed) ContractEventName() string {
// Solidity: event indexed(address indexed addr, int256 indexed num) // Solidity: event indexed(address indexed addr, int256 indexed num)
func (eventChecker *EventChecker) UnpackIndexedEvent(log *types.Log) (*EventCheckerIndexed, error) { func (eventChecker *EventChecker) UnpackIndexedEvent(log *types.Log) (*EventCheckerIndexed, error) {
event := "indexed" event := "indexed"
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != eventChecker.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(EventCheckerIndexed) out := new(EventCheckerIndexed)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -196,8 +210,11 @@ func (EventCheckerMixed) ContractEventName() string {
// Solidity: event mixed(address indexed addr, int256 num) // Solidity: event mixed(address indexed addr, int256 num)
func (eventChecker *EventChecker) UnpackMixedEvent(log *types.Log) (*EventCheckerMixed, error) { func (eventChecker *EventChecker) UnpackMixedEvent(log *types.Log) (*EventCheckerMixed, error) {
event := "mixed" event := "mixed"
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != eventChecker.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(EventCheckerMixed) out := new(EventCheckerMixed)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -238,8 +255,11 @@ func (EventCheckerUnnamed) ContractEventName() string {
// Solidity: event unnamed(uint256 indexed arg0, uint256 indexed arg1) // Solidity: event unnamed(uint256 indexed arg0, uint256 indexed arg1)
func (eventChecker *EventChecker) UnpackUnnamedEvent(log *types.Log) (*EventCheckerUnnamed, error) { func (eventChecker *EventChecker) UnpackUnnamedEvent(log *types.Log) (*EventCheckerUnnamed, error) {
event := "unnamed" event := "unnamed"
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != eventChecker.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(EventCheckerUnnamed) out := new(EventCheckerUnnamed)
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -36,6 +36,11 @@ type Getter struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Getter) GetABI() abi.ABI {
return c.abi
}
// NewGetter creates a new instance of Getter. // NewGetter creates a new instance of Getter.
func NewGetter() *Getter { func NewGetter() *Getter {
parsed, err := GetterMetaData.ParseABI() parsed, err := GetterMetaData.ParseABI()

View file

@ -36,6 +36,11 @@ type IdentifierCollision struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *IdentifierCollision) GetABI() abi.ABI {
return c.abi
}
// NewIdentifierCollision creates a new instance of IdentifierCollision. // NewIdentifierCollision creates a new instance of IdentifierCollision.
func NewIdentifierCollision() *IdentifierCollision { func NewIdentifierCollision() *IdentifierCollision {
parsed, err := IdentifierCollisionMetaData.ParseABI() parsed, err := IdentifierCollisionMetaData.ParseABI()

View file

@ -35,6 +35,11 @@ type InputChecker struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *InputChecker) GetABI() abi.ABI {
return c.abi
}
// NewInputChecker creates a new instance of InputChecker. // NewInputChecker creates a new instance of InputChecker.
func NewInputChecker() *InputChecker { func NewInputChecker() *InputChecker {
parsed, err := InputCheckerMetaData.ParseABI() parsed, err := InputCheckerMetaData.ParseABI()

View file

@ -36,6 +36,11 @@ type Interactor struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Interactor) GetABI() abi.ABI {
return c.abi
}
// NewInteractor creates a new instance of Interactor. // NewInteractor creates a new instance of Interactor.
func NewInteractor() *Interactor { func NewInteractor() *Interactor {
parsed, err := InteractorMetaData.ParseABI() parsed, err := InteractorMetaData.ParseABI()

View file

@ -42,6 +42,11 @@ type NameConflict struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *NameConflict) GetABI() abi.ABI {
return c.abi
}
// NewNameConflict creates a new instance of NameConflict. // NewNameConflict creates a new instance of NameConflict.
func NewNameConflict() *NameConflict { func NewNameConflict() *NameConflict {
parsed, err := NameConflictMetaData.ParseABI() parsed, err := NameConflictMetaData.ParseABI()
@ -134,8 +139,11 @@ func (NameConflictLog) ContractEventName() string {
// Solidity: event log(int256 msg, int256 _msg) // Solidity: event log(int256 msg, int256 _msg)
func (nameConflict *NameConflict) UnpackLogEvent(log *types.Log) (*NameConflictLog, error) { func (nameConflict *NameConflict) UnpackLogEvent(log *types.Log) (*NameConflictLog, error) {
event := "log" event := "log"
if len(log.Topics) == 0 || log.Topics[0] != nameConflict.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != nameConflict.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(NameConflictLog) out := new(NameConflictLog)
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -36,6 +36,11 @@ type NumericMethodName struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *NumericMethodName) GetABI() abi.ABI {
return c.abi
}
// NewNumericMethodName creates a new instance of NumericMethodName. // NewNumericMethodName creates a new instance of NumericMethodName.
func NewNumericMethodName() *NumericMethodName { func NewNumericMethodName() *NumericMethodName {
parsed, err := NumericMethodNameMetaData.ParseABI() parsed, err := NumericMethodNameMetaData.ParseABI()
@ -136,8 +141,11 @@ func (NumericMethodNameE1TestEvent) ContractEventName() string {
// Solidity: event _1TestEvent(address _param) // Solidity: event _1TestEvent(address _param)
func (numericMethodName *NumericMethodName) UnpackE1TestEventEvent(log *types.Log) (*NumericMethodNameE1TestEvent, error) { func (numericMethodName *NumericMethodName) UnpackE1TestEventEvent(log *types.Log) (*NumericMethodNameE1TestEvent, error) {
event := "_1TestEvent" event := "_1TestEvent"
if len(log.Topics) == 0 || log.Topics[0] != numericMethodName.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != numericMethodName.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(NumericMethodNameE1TestEvent) out := new(NumericMethodNameE1TestEvent)
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -35,6 +35,11 @@ type OutputChecker struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *OutputChecker) GetABI() abi.ABI {
return c.abi
}
// NewOutputChecker creates a new instance of OutputChecker. // NewOutputChecker creates a new instance of OutputChecker.
func NewOutputChecker() *OutputChecker { func NewOutputChecker() *OutputChecker {
parsed, err := OutputCheckerMetaData.ParseABI() parsed, err := OutputCheckerMetaData.ParseABI()

View file

@ -36,6 +36,11 @@ type Overload struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Overload) GetABI() abi.ABI {
return c.abi
}
// NewOverload creates a new instance of Overload. // NewOverload creates a new instance of Overload.
func NewOverload() *Overload { func NewOverload() *Overload {
parsed, err := OverloadMetaData.ParseABI() parsed, err := OverloadMetaData.ParseABI()
@ -114,8 +119,11 @@ func (OverloadBar) ContractEventName() string {
// Solidity: event bar(uint256 i) // Solidity: event bar(uint256 i)
func (overload *Overload) UnpackBarEvent(log *types.Log) (*OverloadBar, error) { func (overload *Overload) UnpackBarEvent(log *types.Log) (*OverloadBar, error) {
event := "bar" event := "bar"
if len(log.Topics) == 0 || log.Topics[0] != overload.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != overload.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(OverloadBar) out := new(OverloadBar)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -156,8 +164,11 @@ func (OverloadBar0) ContractEventName() string {
// Solidity: event bar(uint256 i, uint256 j) // Solidity: event bar(uint256 i, uint256 j)
func (overload *Overload) UnpackBar0Event(log *types.Log) (*OverloadBar0, error) { func (overload *Overload) UnpackBar0Event(log *types.Log) (*OverloadBar0, error) {
event := "bar0" event := "bar0"
if len(log.Topics) == 0 || log.Topics[0] != overload.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != overload.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(OverloadBar0) out := new(OverloadBar0)
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -36,6 +36,11 @@ type RangeKeyword struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *RangeKeyword) GetABI() abi.ABI {
return c.abi
}
// NewRangeKeyword creates a new instance of RangeKeyword. // NewRangeKeyword creates a new instance of RangeKeyword.
func NewRangeKeyword() *RangeKeyword { func NewRangeKeyword() *RangeKeyword {
parsed, err := RangeKeywordMetaData.ParseABI() parsed, err := RangeKeywordMetaData.ParseABI()

View file

@ -36,6 +36,11 @@ type Slicer struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Slicer) GetABI() abi.ABI {
return c.abi
}
// NewSlicer creates a new instance of Slicer. // NewSlicer creates a new instance of Slicer.
func NewSlicer() *Slicer { func NewSlicer() *Slicer {
parsed, err := SlicerMetaData.ParseABI() parsed, err := SlicerMetaData.ParseABI()

View file

@ -41,6 +41,11 @@ type Structs struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Structs) GetABI() abi.ABI {
return c.abi
}
// NewStructs creates a new instance of Structs. // NewStructs creates a new instance of Structs.
func NewStructs() *Structs { func NewStructs() *Structs {
parsed, err := StructsMetaData.ParseABI() parsed, err := StructsMetaData.ParseABI()

View file

@ -36,6 +36,11 @@ type Token struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Token) GetABI() abi.ABI {
return c.abi
}
// NewToken creates a new instance of Token. // NewToken creates a new instance of Token.
func NewToken() *Token { func NewToken() *Token {
parsed, err := TokenMetaData.ParseABI() parsed, err := TokenMetaData.ParseABI()
@ -386,8 +391,11 @@ func (TokenTransfer) ContractEventName() string {
// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) // Solidity: event Transfer(address indexed from, address indexed to, uint256 value)
func (token *Token) UnpackTransferEvent(log *types.Log) (*TokenTransfer, error) { func (token *Token) UnpackTransferEvent(log *types.Log) (*TokenTransfer, error) {
event := "Transfer" event := "Transfer"
if len(log.Topics) == 0 || log.Topics[0] != token.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != token.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(TokenTransfer) out := new(TokenTransfer)
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -61,6 +61,11 @@ type Tuple struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Tuple) GetABI() abi.ABI {
return c.abi
}
// NewTuple creates a new instance of Tuple. // NewTuple creates a new instance of Tuple.
func NewTuple() *Tuple { func NewTuple() *Tuple {
parsed, err := TupleMetaData.ParseABI() parsed, err := TupleMetaData.ParseABI()
@ -193,8 +198,11 @@ func (TupleTupleEvent) ContractEventName() string {
// Solidity: event TupleEvent((uint256,uint256[],(uint256,uint256)[]) a, (uint256,uint256)[2][] b, (uint256,uint256)[][2] c, (uint256,uint256[],(uint256,uint256)[])[] d, uint256[] e) // Solidity: event TupleEvent((uint256,uint256[],(uint256,uint256)[]) a, (uint256,uint256)[2][] b, (uint256,uint256)[][2] c, (uint256,uint256[],(uint256,uint256)[])[] d, uint256[] e)
func (tuple *Tuple) UnpackTupleEventEvent(log *types.Log) (*TupleTupleEvent, error) { func (tuple *Tuple) UnpackTupleEventEvent(log *types.Log) (*TupleTupleEvent, error) {
event := "TupleEvent" event := "TupleEvent"
if len(log.Topics) == 0 || log.Topics[0] != tuple.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != tuple.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(TupleTupleEvent) out := new(TupleTupleEvent)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -234,8 +242,11 @@ func (TupleTupleEvent2) ContractEventName() string {
// Solidity: event TupleEvent2((uint8,uint8)[] arg0) // Solidity: event TupleEvent2((uint8,uint8)[] arg0)
func (tuple *Tuple) UnpackTupleEvent2Event(log *types.Log) (*TupleTupleEvent2, error) { func (tuple *Tuple) UnpackTupleEvent2Event(log *types.Log) (*TupleTupleEvent2, error) {
event := "TupleEvent2" event := "TupleEvent2"
if len(log.Topics) == 0 || log.Topics[0] != tuple.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != tuple.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(TupleTupleEvent2) out := new(TupleTupleEvent2)
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -36,6 +36,11 @@ type Tupler struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Tupler) GetABI() abi.ABI {
return c.abi
}
// NewTupler creates a new instance of Tupler. // NewTupler creates a new instance of Tupler.
func NewTupler() *Tupler { func NewTupler() *Tupler {
parsed, err := TuplerMetaData.ParseABI() parsed, err := TuplerMetaData.ParseABI()

View file

@ -36,6 +36,11 @@ type Underscorer struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *Underscorer) GetABI() abi.ABI {
return c.abi
}
// NewUnderscorer creates a new instance of Underscorer. // NewUnderscorer creates a new instance of Underscorer.
func NewUnderscorer() *Underscorer { func NewUnderscorer() *Underscorer {
parsed, err := UnderscorerMetaData.ParseABI() parsed, err := UnderscorerMetaData.ParseABI()

View file

@ -112,7 +112,7 @@ func (arguments Arguments) UnpackIntoMap(v map[string]any, data []byte) error {
// Copy performs the operation go format -> provided struct. // Copy performs the operation go format -> provided struct.
func (arguments Arguments) Copy(v any, values []any) error { func (arguments Arguments) Copy(v any, values []any) error {
// make sure the passed value is arguments pointer // make sure the passed value is arguments pointer
if reflect.Ptr != reflect.ValueOf(v).Kind() { if reflect.Pointer != reflect.ValueOf(v).Kind() {
return fmt.Errorf("abi: Unpack(non-pointer %T)", v) return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
} }
if len(values) == 0 { if len(values) == 0 {
@ -165,7 +165,7 @@ func (arguments Arguments) copyTuple(v any, marshalledValues []any) error {
} }
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
if value.Len() < len(marshalledValues) { if value.Len() < len(marshalledValues) {
return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len()) return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(marshalledValues), value.Len())
} }
for i := range nonIndexedArgs { for i := range nonIndexedArgs {
if err := set(value.Index(i), reflect.ValueOf(marshalledValues[i])); err != nil { if err := set(value.Index(i), reflect.ValueOf(marshalledValues[i])); err != nil {

View file

@ -176,6 +176,13 @@ var (
// ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves // ErrNoCodeAfterDeploy is returned by WaitDeployed if contract creation leaves
// an empty contract behind. // an empty contract behind.
ErrNoCodeAfterDeploy = bind2.ErrNoCodeAfterDeploy ErrNoCodeAfterDeploy = bind2.ErrNoCodeAfterDeploy
// ErrNoEventSignature is returned when a log entry has no topics.
ErrNoEventSignature = bind2.ErrNoEventSignature
// ErrEventSignatureMismatch is returned when a log's topic[0] does not match
// the expected event signature.
ErrEventSignatureMismatch = bind2.ErrEventSignatureMismatch
) )
// ContractCaller defines the methods needed to allow operating with a contract on a read // ContractCaller defines the methods needed to allow operating with a contract on a read
@ -266,6 +273,12 @@ func (m *MetaData) GetAbi() (*abi.ABI, error) {
// util.go // util.go
// WaitAccepted waits for a tx to be accepted into the pool.
// It stops waiting when the context is canceled.
func WaitAccepted(ctx context.Context, b ContractBackend, tx *types.Transaction) error {
return bind2.WaitAccepted(ctx, b, tx.Hash())
}
// WaitMined waits for tx to be mined on the blockchain. // WaitMined waits for tx to be mined on the blockchain.
// It stops waiting when the context is canceled. // It stops waiting when the context is canceled.
func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) { func WaitMined(ctx context.Context, b DeployBackend, tx *types.Transaction) (*types.Receipt, error) {

View file

@ -103,6 +103,9 @@ type ContractTransactor interface {
// PendingNonceAt retrieves the current pending nonce associated with an account. // PendingNonceAt retrieves the current pending nonce associated with an account.
PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
// TransactionByHash retrieves the transaction associated with the hash, if it exists in the pool.
TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error)
} }
// DeployBackend wraps the operations needed by WaitMined and WaitDeployed. // DeployBackend wraps the operations needed by WaitMined and WaitDeployed.

View file

@ -35,8 +35,8 @@ import (
const basefeeWiggleMultiplier = 2 const basefeeWiggleMultiplier = 2
var ( var (
errNoEventSignature = errors.New("no event signature") ErrNoEventSignature = errors.New("no event signature")
errEventSignatureMismatch = errors.New("event signature mismatch") ErrEventSignatureMismatch = errors.New("event signature mismatch")
) )
// SignerFn is a signer function callback when a contract requires a method to // SignerFn is a signer function callback when a contract requires a method to
@ -320,7 +320,7 @@ func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Add
} }
} }
// create the transaction // create the transaction
nonce, err := c.getNonce(opts) nonce, err := c.GetNonce(opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -365,7 +365,7 @@ func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Addr
} }
} }
// create the transaction // create the transaction
nonce, err := c.getNonce(opts) nonce, err := c.GetNonce(opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -402,7 +402,7 @@ func (c *BoundContract) estimateGasLimit(opts *TransactOpts, contract *common.Ad
return c.transactor.EstimateGas(ensureContext(opts.Context), msg) return c.transactor.EstimateGas(ensureContext(opts.Context), msg)
} }
func (c *BoundContract) getNonce(opts *TransactOpts) (uint64, error) { func (c *BoundContract) GetNonce(opts *TransactOpts) (uint64, error) {
if opts.Nonce == nil { if opts.Nonce == nil {
return c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From) return c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From)
} else { } else {
@ -536,10 +536,10 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]any)
func (c *BoundContract) UnpackLog(out any, event string, log types.Log) error { func (c *BoundContract) UnpackLog(out any, event string, log types.Log) error {
// Anonymous events are not supported. // Anonymous events are not supported.
if len(log.Topics) == 0 { if len(log.Topics) == 0 {
return errNoEventSignature return ErrNoEventSignature
} }
if log.Topics[0] != c.abi.Events[event].ID { if log.Topics[0] != c.abi.Events[event].ID {
return errEventSignatureMismatch return ErrEventSignatureMismatch
} }
if len(log.Data) > 0 { if len(log.Data) > 0 {
if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil { if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
@ -559,10 +559,10 @@ func (c *BoundContract) UnpackLog(out any, event string, log types.Log) error {
func (c *BoundContract) UnpackLogIntoMap(out map[string]any, event string, log types.Log) error { func (c *BoundContract) UnpackLogIntoMap(out map[string]any, event string, log types.Log) error {
// Anonymous events are not supported. // Anonymous events are not supported.
if len(log.Topics) == 0 { if len(log.Topics) == 0 {
return errNoEventSignature return ErrNoEventSignature
} }
if log.Topics[0] != c.abi.Events[event].ID { if log.Topics[0] != c.abi.Events[event].ID {
return errEventSignatureMismatch return ErrEventSignatureMismatch
} }
if len(log.Data) > 0 { if len(log.Data) > 0 {
if err := c.abi.UnpackIntoMap(out, event, log.Data); err != nil { if err := c.abi.UnpackIntoMap(out, event, log.Data); err != nil {

View file

@ -75,6 +75,10 @@ func (mt *mockTransactor) SendTransaction(ctx context.Context, tx *types.Transac
return nil return nil
} }
func (mt *mockTransactor) TransactionByHash(ctx context.Context, hash common.Hash) (*types.Transaction, bool, error) {
return nil, false, nil
}
type mockCaller struct { type mockCaller struct {
codeAtBlockNumber *big.Int codeAtBlockNumber *big.Int
callContractBlockNumber *big.Int callContractBlockNumber *big.Int

View file

@ -329,7 +329,7 @@ func TestContractLinking(t *testing.T) {
map[rune]struct{}{}, map[rune]struct{}{},
}, },
// two contracts ('a' and 'f') share some dependencies. contract 'a' is marked as an override. expect that any of // two contracts ('a' and 'f') share some dependencies. contract 'a' is marked as an override. expect that any of
// its depdencies that aren't shared with 'f' are not deployed. // its dependencies that aren't shared with 'f' are not deployed.
linkTestCaseInput{map[rune][]rune{ linkTestCaseInput{map[rune][]rune{
'a': {'b', 'c', 'd', 'e'}, 'a': {'b', 'c', 'd', 'e'},
'f': {'g', 'c', 'd', 'h'}}, 'f': {'g', 'c', 'd', 'h'}},

View file

@ -43,6 +43,11 @@ type DB struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *DB) GetABI() abi.ABI {
return c.abi
}
// NewDB creates a new instance of DB. // NewDB creates a new instance of DB.
func NewDB() *DB { func NewDB() *DB {
parsed, err := DBMetaData.ParseABI() parsed, err := DBMetaData.ParseABI()
@ -276,8 +281,11 @@ func (DBInsert) ContractEventName() string {
// Solidity: event Insert(uint256 key, uint256 value, uint256 length) // Solidity: event Insert(uint256 key, uint256 value, uint256 length)
func (dB *DB) UnpackInsertEvent(log *types.Log) (*DBInsert, error) { func (dB *DB) UnpackInsertEvent(log *types.Log) (*DBInsert, error) {
event := "Insert" event := "Insert"
if len(log.Topics) == 0 || log.Topics[0] != dB.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != dB.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(DBInsert) out := new(DBInsert)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -318,8 +326,11 @@ func (DBKeyedInsert) ContractEventName() string {
// Solidity: event KeyedInsert(uint256 indexed key, uint256 value) // Solidity: event KeyedInsert(uint256 indexed key, uint256 value)
func (dB *DB) UnpackKeyedInsertEvent(log *types.Log) (*DBKeyedInsert, error) { func (dB *DB) UnpackKeyedInsertEvent(log *types.Log) (*DBKeyedInsert, error) {
event := "KeyedInsert" event := "KeyedInsert"
if len(log.Topics) == 0 || log.Topics[0] != dB.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != dB.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(DBKeyedInsert) out := new(DBKeyedInsert)
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -36,6 +36,11 @@ type C struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *C) GetABI() abi.ABI {
return c.abi
}
// NewC creates a new instance of C. // NewC creates a new instance of C.
func NewC() *C { func NewC() *C {
parsed, err := CMetaData.ParseABI() parsed, err := CMetaData.ParseABI()
@ -115,8 +120,11 @@ func (CBasic1) ContractEventName() string {
// Solidity: event basic1(uint256 indexed id, uint256 data) // Solidity: event basic1(uint256 indexed id, uint256 data)
func (c *C) UnpackBasic1Event(log *types.Log) (*CBasic1, error) { func (c *C) UnpackBasic1Event(log *types.Log) (*CBasic1, error) {
event := "basic1" event := "basic1"
if len(log.Topics) == 0 || log.Topics[0] != c.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != c.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(CBasic1) out := new(CBasic1)
if len(log.Data) > 0 { if len(log.Data) > 0 {
@ -157,8 +165,11 @@ func (CBasic2) ContractEventName() string {
// Solidity: event basic2(bool indexed flag, uint256 data) // Solidity: event basic2(bool indexed flag, uint256 data)
func (c *C) UnpackBasic2Event(log *types.Log) (*CBasic2, error) { func (c *C) UnpackBasic2Event(log *types.Log) (*CBasic2, error) {
event := "basic2" event := "basic2"
if len(log.Topics) == 0 || log.Topics[0] != c.abi.Events[event].ID { if len(log.Topics) == 0 {
return nil, errors.New("event signature mismatch") return nil, bind.ErrNoEventSignature
}
if log.Topics[0] != c.abi.Events[event].ID {
return nil, bind.ErrEventSignatureMismatch
} }
out := new(CBasic2) out := new(CBasic2)
if len(log.Data) > 0 { if len(log.Data) > 0 {

View file

@ -40,6 +40,11 @@ type C1 struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *C1) GetABI() abi.ABI {
return c.abi
}
// NewC1 creates a new instance of C1. // NewC1 creates a new instance of C1.
func NewC1() *C1 { func NewC1() *C1 {
parsed, err := C1MetaData.ParseABI() parsed, err := C1MetaData.ParseABI()
@ -118,6 +123,11 @@ type C2 struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *C2) GetABI() abi.ABI {
return c.abi
}
// NewC2 creates a new instance of C2. // NewC2 creates a new instance of C2.
func NewC2() *C2 { func NewC2() *C2 {
parsed, err := C2MetaData.ParseABI() parsed, err := C2MetaData.ParseABI()
@ -192,6 +202,11 @@ type L1 struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *L1) GetABI() abi.ABI {
return c.abi
}
// NewL1 creates a new instance of L1. // NewL1 creates a new instance of L1.
func NewL1() *L1 { func NewL1() *L1 {
parsed, err := L1MetaData.ParseABI() parsed, err := L1MetaData.ParseABI()
@ -257,6 +272,11 @@ type L2 struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *L2) GetABI() abi.ABI {
return c.abi
}
// NewL2 creates a new instance of L2. // NewL2 creates a new instance of L2.
func NewL2() *L2 { func NewL2() *L2 {
parsed, err := L2MetaData.ParseABI() parsed, err := L2MetaData.ParseABI()
@ -322,6 +342,11 @@ type L2b struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *L2b) GetABI() abi.ABI {
return c.abi
}
// NewL2b creates a new instance of L2b. // NewL2b creates a new instance of L2b.
func NewL2b() *L2b { func NewL2b() *L2b {
parsed, err := L2bMetaData.ParseABI() parsed, err := L2bMetaData.ParseABI()
@ -384,6 +409,11 @@ type L3 struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *L3) GetABI() abi.ABI {
return c.abi
}
// NewL3 creates a new instance of L3. // NewL3 creates a new instance of L3.
func NewL3() *L3 { func NewL3() *L3 {
parsed, err := L3MetaData.ParseABI() parsed, err := L3MetaData.ParseABI()
@ -450,6 +480,11 @@ type L4 struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *L4) GetABI() abi.ABI {
return c.abi
}
// NewL4 creates a new instance of L4. // NewL4 creates a new instance of L4.
func NewL4() *L4 { func NewL4() *L4 {
parsed, err := L4MetaData.ParseABI() parsed, err := L4MetaData.ParseABI()
@ -515,6 +550,11 @@ type L4b struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *L4b) GetABI() abi.ABI {
return c.abi
}
// NewL4b creates a new instance of L4b. // NewL4b creates a new instance of L4b.
func NewL4b() *L4b { func NewL4b() *L4b {
parsed, err := L4bMetaData.ParseABI() parsed, err := L4bMetaData.ParseABI()

View file

@ -36,6 +36,11 @@ type C struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *C) GetABI() abi.ABI {
return c.abi
}
// NewC creates a new instance of C. // NewC creates a new instance of C.
func NewC() *C { func NewC() *C {
parsed, err := CMetaData.ParseABI() parsed, err := CMetaData.ParseABI()
@ -173,6 +178,11 @@ type C2 struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *C2) GetABI() abi.ABI {
return c.abi
}
// NewC2 creates a new instance of C2. // NewC2 creates a new instance of C2.
func NewC2() *C2 { func NewC2() *C2 {
parsed, err := C2MetaData.ParseABI() parsed, err := C2MetaData.ParseABI()

View file

@ -36,6 +36,11 @@ type MyContract struct {
abi abi.ABI abi abi.ABI
} }
// GetABI returns the ABI associated with this contract binding.
func (c *MyContract) GetABI() abi.ABI {
return c.abi
}
// NewMyContract creates a new instance of MyContract. // NewMyContract creates a new instance of MyContract.
func NewMyContract() *MyContract { func NewMyContract() *MyContract {
parsed, err := MyContractMetaData.ParseABI() parsed, err := MyContractMetaData.ParseABI()

View file

@ -310,7 +310,7 @@ done:
t.Fatalf("expected e1Count of 2 from filter call. got %d", e1Count) t.Fatalf("expected e1Count of 2 from filter call. got %d", e1Count)
} }
if e2Count != 1 { if e2Count != 1 {
t.Fatalf("expected e2Count of 1 from filter call. got %d", e1Count) t.Fatalf("expected e2Count of 1 from filter call. got %d", e2Count)
} }
} }
@ -379,16 +379,16 @@ func TestEventUnpackEmptyTopics(t *testing.T) {
if err == nil { if err == nil {
t.Fatal("expected error when unpacking event with empty topics, got nil") t.Fatal("expected error when unpacking event with empty topics, got nil")
} }
if err.Error() != "event signature mismatch" { if err != bind.ErrNoEventSignature {
t.Fatalf("expected 'event signature mismatch' error, got: %v", err) t.Fatalf("expected 'no event signature' error, got: %v", err)
} }
_, err = c.UnpackBasic2Event(log) _, err = c.UnpackBasic2Event(log)
if err == nil { if err == nil {
t.Fatal("expected error when unpacking event with empty topics, got nil") t.Fatal("expected error when unpacking event with empty topics, got nil")
} }
if err.Error() != "event signature mismatch" { if err != bind.ErrNoEventSignature {
t.Fatalf("expected 'event signature mismatch' error, got: %v", err) t.Fatalf("expected 'no event signature' error, got: %v", err)
} }
} }
} }

View file

@ -75,3 +75,28 @@ func WaitDeployed(ctx context.Context, b DeployBackend, hash common.Hash) (commo
} }
return receipt.ContractAddress, err return receipt.ContractAddress, err
} }
func WaitAccepted(ctx context.Context, d ContractBackend, txHash common.Hash) error {
queryTicker := time.NewTicker(time.Second)
defer queryTicker.Stop()
logger := log.New("hash", txHash)
for {
_, _, err := d.TransactionByHash(ctx, txHash)
if err == nil {
return nil
}
if errors.Is(err, ethereum.NotFound) { // TODO: check this is emitted
logger.Trace("Transaction not yet accepted")
} else {
logger.Trace("Transaction submission failed", "err", err)
}
// Wait for the next round.
select {
case <-ctx.Done():
return ctx.Err()
case <-queryTicker.C:
}
}
}

View file

@ -39,7 +39,7 @@ func packElement(t Type, reflectValue reflect.Value) ([]byte, error) {
switch t.T { switch t.T {
case UintTy: case UintTy:
// make sure to not pack a negative value into a uint type. // make sure to not pack a negative value into a uint type.
if reflectValue.Kind() == reflect.Ptr { if reflectValue.Kind() == reflect.Pointer {
val := new(big.Int).Set(reflectValue.Interface().(*big.Int)) val := new(big.Int).Set(reflectValue.Interface().(*big.Int))
if val.Sign() == -1 { if val.Sign() == -1 {
return nil, errInvalidSign return nil, errInvalidSign
@ -86,7 +86,7 @@ func packNum(value reflect.Value) []byte {
return math.U256Bytes(new(big.Int).SetUint64(value.Uint())) return math.U256Bytes(new(big.Int).SetUint64(value.Uint()))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return math.U256Bytes(big.NewInt(value.Int())) return math.U256Bytes(big.NewInt(value.Int()))
case reflect.Ptr: case reflect.Pointer:
return math.U256Bytes(new(big.Int).Set(value.Interface().(*big.Int))) return math.U256Bytes(new(big.Int).Set(value.Interface().(*big.Int)))
default: default:
panic("abi: fatal error") panic("abi: fatal error")

View file

@ -53,7 +53,7 @@ func ConvertType(in interface{}, proto interface{}) interface{} {
// indirect recursively dereferences the value until it either gets the value // indirect recursively dereferences the value until it either gets the value
// or finds a big.Int // or finds a big.Int
func indirect(v reflect.Value) reflect.Value { func indirect(v reflect.Value) reflect.Value {
if v.Kind() == reflect.Ptr && v.Elem().Type() != reflect.TypeFor[big.Int]() { if v.Kind() == reflect.Pointer && v.Elem().Type() != reflect.TypeFor[big.Int]() {
return indirect(v.Elem()) return indirect(v.Elem())
} }
return v return v
@ -102,9 +102,9 @@ func mustArrayToByteSlice(value reflect.Value) reflect.Value {
func set(dst, src reflect.Value) error { func set(dst, src reflect.Value) error {
dstType, srcType := dst.Type(), src.Type() dstType, srcType := dst.Type(), src.Type()
switch { switch {
case dstType.Kind() == reflect.Interface && dst.Elem().IsValid() && (dst.Elem().Type().Kind() == reflect.Ptr || dst.Elem().CanSet()): case dstType.Kind() == reflect.Interface && dst.Elem().IsValid() && (dst.Elem().Type().Kind() == reflect.Pointer || dst.Elem().CanSet()):
return set(dst.Elem(), src) return set(dst.Elem(), src)
case dstType.Kind() == reflect.Ptr && dstType.Elem() != reflect.TypeFor[big.Int](): case dstType.Kind() == reflect.Pointer && dstType.Elem() != reflect.TypeFor[big.Int]():
return set(dst.Elem(), src) return set(dst.Elem(), src)
case srcType.AssignableTo(dstType) && dst.CanSet(): case srcType.AssignableTo(dstType) && dst.CanSet():
dst.Set(src) dst.Set(src)
@ -138,7 +138,7 @@ func setSlice(dst, src reflect.Value) error {
} }
func setArray(dst, src reflect.Value) error { func setArray(dst, src reflect.Value) error {
if src.Kind() == reflect.Ptr { if src.Kind() == reflect.Pointer {
return set(dst, indirect(src)) return set(dst, indirect(src))
} }
array := reflect.New(dst.Type()).Elem() array := reflect.New(dst.Type()).Elem()

View file

@ -75,8 +75,11 @@ func parseElementaryType(unescapedSelector string) (string, string, error) {
parsedType = parsedType + string(rest[0]) parsedType = parsedType + string(rest[0])
rest = rest[1:] rest = rest[1:]
} }
if len(rest) == 0 || rest[0] != ']' { if len(rest) == 0 {
return "", "", fmt.Errorf("failed to parse array: expected ']', got %c", unescapedSelector[0]) return "", "", fmt.Errorf("failed to parse array: expected ']', got end of string")
}
if rest[0] != ']' {
return "", "", fmt.Errorf("failed to parse array: expected ']', got %c", rest[0])
} }
parsedType = parsedType + string(rest[0]) parsedType = parsedType + string(rest[0])
rest = rest[1:] rest = rest[1:]

View file

@ -154,7 +154,7 @@ func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error)
return nil, fmt.Errorf("cannot marshal input to array, size is negative (%d)", size) return nil, fmt.Errorf("cannot marshal input to array, size is negative (%d)", size)
} }
if start+32*size > len(output) { if start+32*size > len(output) {
return nil, fmt.Errorf("abi: cannot marshal into go array: offset %d would go over slice boundary (len=%d)", len(output), start+32*size) return nil, fmt.Errorf("abi: cannot marshal into go array: offset %d would go over slice boundary (len=%d)", start+32*size, len(output))
} }
// this value will become our slice or our array, depending on the type // this value will become our slice or our array, depending on the type

View file

@ -910,7 +910,7 @@ func TestUnpackTuple(t *testing.T) {
}, },
}, },
FieldT: T{ FieldT: T{
big.NewInt(0), big.NewInt(1), big.NewInt(0).SetBits([]big.Word{}), big.NewInt(1),
}, },
A: big.NewInt(1), A: big.NewInt(1),
} }
@ -919,7 +919,7 @@ func TestUnpackTuple(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
if reflect.DeepEqual(ret, expected) { if !reflect.DeepEqual(ret, expected) {
t.Error("unexpected unpack value") t.Error("unexpected unpack value")
} }
} }

View file

@ -237,6 +237,7 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
} }
if tx.Type() == types.BlobTxType { if tx.Type() == types.BlobTxType {
args.BlobHashes = tx.BlobHashes() args.BlobHashes = tx.BlobHashes()
args.BlobFeeCap = (*hexutil.Big)(tx.BlobGasFeeCap())
sidecar := tx.BlobTxSidecar() sidecar := tx.BlobTxSidecar()
if sidecar == nil { if sidecar == nil {
return nil, errors.New("blobs must be present for signing") return nil, errors.New("blobs must be present for signing")

View file

@ -68,18 +68,27 @@ func waitWatcherStart(ks *KeyStore) bool {
func waitForAccounts(wantAccounts []accounts.Account, ks *KeyStore) error { func waitForAccounts(wantAccounts []accounts.Account, ks *KeyStore) error {
var list []accounts.Account var list []accounts.Account
haveAccounts := false
haveChange := false
for t0 := time.Now(); time.Since(t0) < 5*time.Second; time.Sleep(100 * time.Millisecond) { for t0 := time.Now(); time.Since(t0) < 5*time.Second; time.Sleep(100 * time.Millisecond) {
if !haveAccounts {
list = ks.Accounts() list = ks.Accounts()
if reflect.DeepEqual(list, wantAccounts) { haveAccounts = reflect.DeepEqual(list, wantAccounts)
// ks should have also received change notifications }
if !haveChange {
select { select {
case <-ks.changes: case <-ks.changes:
haveChange = true
default: default:
return errors.New("wasn't notified of new accounts")
} }
}
if haveAccounts && haveChange {
return nil return nil
} }
} }
if haveAccounts {
return errors.New("wasn't notified of new accounts")
}
return fmt.Errorf("\ngot %v\nwant %v", list, wantAccounts) return fmt.Errorf("\ngot %v\nwant %v", list, wantAccounts)
} }

View file

@ -230,7 +230,7 @@ func toISO8601(t time.Time) string {
if name == "UTC" { if name == "UTC" {
tz = "Z" tz = "Z"
} else { } else {
tz = fmt.Sprintf("%03d00", offset/3600) tz = fmt.Sprintf("%+03d00", offset/3600)
} }
return fmt.Sprintf("%04d-%02d-%02dT%02d-%02d-%02d.%09d%s", return fmt.Sprintf("%04d-%02d-%02dT%02d-%02d-%02d.%09d%s",
t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), tz) t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), tz)

View file

@ -14,8 +14,8 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
//go:build (darwin && !ios && cgo) || freebsd || (linux && !arm64) || netbsd || solaris //go:build (darwin && !ios && cgo) || freebsd || linux || netbsd || solaris
// +build darwin,!ios,cgo freebsd linux,!arm64 netbsd solaris // +build darwin,!ios,cgo freebsd linux netbsd solaris
package keystore package keystore

View file

@ -14,8 +14,8 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
//go:build (darwin && !cgo) || ios || (linux && arm64) || windows || (!darwin && !freebsd && !linux && !netbsd && !solaris) //go:build (darwin && !cgo) || ios || windows || (!darwin && !freebsd && !linux && !netbsd && !solaris)
// +build darwin,!cgo ios linux,arm64 windows !darwin,!freebsd,!linux,!netbsd,!solaris // +build darwin,!cgo ios windows !darwin,!freebsd,!linux,!netbsd,!solaris
// This is the fallback implementation of directory watching. // This is the fallback implementation of directory watching.
// It is used on unsupported platforms. // It is used on unsupported platforms.

View file

@ -18,6 +18,7 @@ package accounts
import ( import (
"reflect" "reflect"
"slices"
"sort" "sort"
"sync" "sync"
@ -254,13 +255,12 @@ func merge(slice []Wallet, wallets ...Wallet) []Wallet {
// drop is the counterpart of merge, which looks up wallets from within the sorted // drop is the counterpart of merge, which looks up wallets from within the sorted
// cache and removes the ones specified. // cache and removes the ones specified.
func drop(slice []Wallet, wallets ...Wallet) []Wallet { func drop(slice []Wallet, wallets ...Wallet) []Wallet {
for _, wallet := range wallets { remove := make(map[URL]struct{}, len(wallets))
n := sort.Search(len(slice), func(i int) bool { return slice[i].URL().Cmp(wallet.URL()) >= 0 }) for _, w := range wallets {
if n == len(slice) { remove[w.URL()] = struct{}{}
// Wallet not found, may happen during startup
continue
} }
slice = append(slice[:n], slice[n+1:]...) return slices.DeleteFunc(slice, func(w Wallet) bool {
} _, ok := remove[w.URL()]
return slice return ok
})
} }

View file

@ -1,4 +1,4 @@
// Copyright 2018 The go-ethereum Authors // Copyright 2026 The go-ethereum Authors
// This file is part of the go-ethereum library. // This file is part of the go-ethereum library.
// //
// The go-ethereum library is free software: you can redistribute it and/or modify // The go-ethereum library is free software: you can redistribute it and/or modify
@ -14,32 +14,34 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core package accounts
import "testing" import "testing"
func TestPasswordValidation(t *testing.T) { type managerTestWallet struct {
Wallet
url URL
}
func (w managerTestWallet) URL() URL {
return w.url
}
func TestDropMissingWallet(t *testing.T) {
t.Parallel() t.Parallel()
testcases := []struct {
pw string wallets := []Wallet{
shouldFail bool managerTestWallet{url: URL{Scheme: "test", Path: "a"}},
}{ managerTestWallet{url: URL{Scheme: "test", Path: "c"}},
{"test", true},
{"testtest\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98", true},
{"placeOfInterest⌘", true},
{"password\nwith\nlinebreak", true},
{"password\twith\vtabs", true},
// Ok passwords
{"password WhichIsOk", false},
{"passwordOk!@#$%^&*()", false},
{"12301203123012301230123012", false},
} }
for _, test := range testcases { dropped := drop(wallets, managerTestWallet{url: URL{Scheme: "test", Path: "b"}})
err := ValidatePasswordFormat(test.pw)
if err == nil && test.shouldFail { if len(dropped) != len(wallets) {
t.Errorf("password '%v' should fail validation", test.pw) t.Fatalf("drop removed wallet for missing URL: got %d wallets, want %d", len(dropped), len(wallets))
} else if err != nil && !test.shouldFail { }
t.Errorf("password '%v' shound not fail validation, but did: %v", test.pw, err) for i := range dropped {
if got, want := dropped[i].URL(), wallets[i].URL(); got != want {
t.Fatalf("wallet %d mismatch: got %v, want %v", i, got, want)
} }
} }
} }

View file

@ -113,7 +113,7 @@ func (hub *Hub) readPairings() error {
} }
func (hub *Hub) writePairings() error { func (hub *Hub) writePairings() error {
pairingFile, err := os.OpenFile(filepath.Join(hub.datadir, "smartcards.json"), os.O_RDWR|os.O_CREATE, 0755) pairingFile, err := os.OpenFile(filepath.Join(hub.datadir, "smartcards.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil { if err != nil {
return err return err
} }
@ -129,11 +129,8 @@ func (hub *Hub) writePairings() error {
return err return err
} }
if _, err := pairingFile.Write(pairingData); err != nil { _, err = pairingFile.Write(pairingData)
return err return err
}
return nil
} }
func (hub *Hub) pairing(wallet *Wallet) *smartcardPairing { func (hub *Hub) pairing(wallet *Wallet) *smartcardPairing {

View file

@ -26,7 +26,7 @@ import (
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/karalabe/hid" "github.com/ethereum/hid"
) )
// LedgerScheme is the protocol scheme prefixing account and wallet URLs. // LedgerScheme is the protocol scheme prefixing account and wallet URLs.

View file

@ -110,6 +110,16 @@ func (w *ledgerDriver) offline() bool {
return w.version == [3]byte{0, 0, 0} return w.version == [3]byte{0, 0, 0}
} }
func ledgerVersionLessThan(version [3]byte, major, minor, patch byte) bool {
if version[0] != major {
return version[0] < major
}
if version[1] != minor {
return version[1] < minor
}
return version[2] < patch
}
// Open implements usbwallet.driver, attempting to initialize the connection to the // Open implements usbwallet.driver, attempting to initialize the connection to the
// Ledger hardware wallet. The Ledger does not require a user passphrase, so that // Ledger hardware wallet. The Ledger does not require a user passphrase, so that
// parameter is silently discarded. // parameter is silently discarded.
@ -166,7 +176,19 @@ func (w *ledgerDriver) SignTx(path accounts.DerivationPath, tx *types.Transactio
return common.Address{}, nil, accounts.ErrWalletClosed return common.Address{}, nil, accounts.ErrWalletClosed
} }
// Ensure the wallet is capable of signing the given transaction // Ensure the wallet is capable of signing the given transaction
if chainID != nil && (w.version[0] < 1 || (w.version[0] == 1 && w.version[1] == 0 && w.version[2] < 3)) { switch tx.Type() {
case types.AccessListTxType, types.DynamicFeeTxType:
if ledgerVersionLessThan(w.version, 1, 9, 0) {
//lint:ignore ST1005 brand name displayed on the console
return common.Address{}, nil, fmt.Errorf("Ledger version >= 1.9.0 required for EIP-2930/EIP-1559 signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2])
}
case types.SetCodeTxType:
if ledgerVersionLessThan(w.version, 1, 17, 0) {
//lint:ignore ST1005 brand name displayed on the console
return common.Address{}, nil, fmt.Errorf("Ledger version >= 1.17.0 required for EIP-7702 signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2])
}
}
if chainID != nil && ledgerVersionLessThan(w.version, 1, 0, 3) {
//lint:ignore ST1005 brand name displayed on the console //lint:ignore ST1005 brand name displayed on the console
return common.Address{}, nil, fmt.Errorf("Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2]) return common.Address{}, nil, fmt.Errorf("Ledger v%d.%d.%d doesn't support signing this transaction, please update to v1.0.3 at least", w.version[0], w.version[1], w.version[2])
} }
@ -184,7 +206,7 @@ func (w *ledgerDriver) SignTypedMessage(path accounts.DerivationPath, domainHash
return nil, accounts.ErrWalletClosed return nil, accounts.ErrWalletClosed
} }
// Ensure the wallet is capable of signing the given transaction // Ensure the wallet is capable of signing the given transaction
if w.version[0] < 1 || (w.version[0] == 1 && w.version[1] < 5) { if ledgerVersionLessThan(w.version, 1, 5, 0) {
//lint:ignore ST1005 brand name displayed on the console //lint:ignore ST1005 brand name displayed on the console
return nil, fmt.Errorf("Ledger version >= 1.5.0 required for EIP-712 signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2]) return nil, fmt.Errorf("Ledger version >= 1.5.0 required for EIP-712 signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2])
} }
@ -334,26 +356,41 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
err error err error
) )
if chainID == nil { if chainID == nil {
if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data()}); err != nil { if txrlp, err = rlp.EncodeToBytes([]any{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data()}); err != nil {
return common.Address{}, nil, err return common.Address{}, nil, err
} }
} else { } else {
if tx.Type() == types.DynamicFeeTxType { switch tx.Type() {
if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasTipCap(), tx.GasFeeCap(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil { case types.SetCodeTxType:
if txrlp, err = rlp.EncodeToBytes([]any{chainID, tx.Nonce(), tx.GasTipCap(), tx.GasFeeCap(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations()}); err != nil {
return common.Address{}, nil, err return common.Address{}, nil, err
} }
// append type to transaction // append type to transaction
txrlp = append([]byte{tx.Type()}, txrlp...) txrlp = append([]byte{tx.Type()}, txrlp...)
} else if tx.Type() == types.AccessListTxType { case types.BlobTxType:
if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil { if txrlp, err = rlp.EncodeToBytes([]any{chainID, tx.Nonce(), tx.GasTipCap(), tx.GasFeeCap(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList(), tx.BlobGasFeeCap(), tx.BlobHashes()}); err != nil {
return common.Address{}, nil, err return common.Address{}, nil, err
} }
// append type to transaction // append type to transaction
txrlp = append([]byte{tx.Type()}, txrlp...) txrlp = append([]byte{tx.Type()}, txrlp...)
} else if tx.Type() == types.LegacyTxType { case types.DynamicFeeTxType:
if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil { if txrlp, err = rlp.EncodeToBytes([]any{chainID, tx.Nonce(), tx.GasTipCap(), tx.GasFeeCap(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil {
return common.Address{}, nil, err return common.Address{}, nil, err
} }
// append type to transaction
txrlp = append([]byte{tx.Type()}, txrlp...)
case types.AccessListTxType:
if txrlp, err = rlp.EncodeToBytes([]any{chainID, tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil {
return common.Address{}, nil, err
}
// append type to transaction
txrlp = append([]byte{tx.Type()}, txrlp...)
case types.LegacyTxType:
if txrlp, err = rlp.EncodeToBytes([]any{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil {
return common.Address{}, nil, err
}
default:
return common.Address{}, nil, fmt.Errorf("unsupported transaction type: %d", tx.Type())
} }
} }
payload := append(path, txrlp...) payload := append(path, txrlp...)

View file

@ -31,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/karalabe/hid" "github.com/ethereum/hid"
) )
// Maximum time between wallet health checks to detect USB unplugs. // Maximum time between wallet health checks to detect USB unplugs.

View file

@ -1,39 +0,0 @@
clone_depth: 5
version: "{branch}.{build}"
image:
- Visual Studio 2019
environment:
matrix:
- GETH_ARCH: amd64
GETH_MINGW: 'C:\msys64\mingw64'
- GETH_ARCH: 386
GETH_MINGW: 'C:\msys64\mingw32'
install:
- git submodule update --init --depth 1 --recursive
- go version
for:
# Windows builds for amd64 + 386.
- matrix:
only:
- image: Visual Studio 2019
environment:
# We use gcc from MSYS2 because it is the most recent compiler version available on
# AppVeyor. Note: gcc.exe only works properly if the corresponding bin/ directory is
# contained in PATH.
GETH_CC: '%GETH_MINGW%\bin\gcc.exe'
PATH: '%GETH_MINGW%\bin;C:\Program Files (x86)\NSIS\;%PATH%'
build_script:
- 'echo %GETH_ARCH%'
- 'echo %GETH_CC%'
- '%GETH_CC% --version'
- go run build/ci.go install -dlgo -arch %GETH_ARCH% -cc %GETH_CC%
after_build:
# Upload builds. Note that ci.go makes this a no-op PR builds.
- go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
- go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
test_script:
- go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -short

View file

@ -87,6 +87,10 @@ func (ec *engineClient) updateLoop(headCh <-chan types.ChainHeadEvent) {
if status, err := ec.callForkchoiceUpdated(forkName, event); err == nil { if status, err := ec.callForkchoiceUpdated(forkName, event); err == nil {
log.Info("Successful ForkchoiceUpdated", "head", event.Block.Hash(), "status", status) log.Info("Successful ForkchoiceUpdated", "head", event.Block.Hash(), "status", status)
} else { } else {
if err.Error() == "beacon syncer reorging" {
log.Debug("Failed ForkchoiceUpdated", "head", event.Block.Hash(), "error", err)
continue // ignore beacon syncer reorging errors, this error can occur if the blsync is skipping a block
}
log.Error("Failed ForkchoiceUpdated", "head", event.Block.Hash(), "error", err) log.Error("Failed ForkchoiceUpdated", "head", event.Block.Hash(), "error", err)
} }
} }

View file

@ -0,0 +1,75 @@
// Copyright 2026 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package engine
import (
"github.com/fjl/jsonw"
)
// MarshalJSON implements json.Marshaler.
func (list BlobAndProofListV1) MarshalJSON() ([]byte, error) {
if list == nil {
return []byte("null"), nil
}
var b jsonw.Buffer
b.Array(func() {
for _, item := range list {
marshalBlobAndProofV1(&b, item)
}
})
return b.Output(), nil
}
func marshalBlobAndProofV1(b *jsonw.Buffer, item *BlobAndProofV1) {
if item == nil {
b.Null()
} else {
b.Object(func() {
b.Key("blob")
b.HexBytes(item.Blob)
b.Key("proof")
b.HexBytes(item.Proof)
})
}
}
// MarshalJSON implements json.Marshaler.
func (list BlobAndProofListV2) MarshalJSON() ([]byte, error) {
if list == nil {
return []byte("null"), nil
}
var b jsonw.Buffer
b.Array(func() {
for _, item := range list {
marshalBlobAndProofV2(&b, item)
}
})
return b.Output(), nil
}
func marshalBlobAndProofV2(b *jsonw.Buffer, item *BlobAndProofV2) {
if item == nil {
b.Null()
} else {
b.Object(func() {
b.Key("blob")
b.HexBytes(item.Blob)
b.Key("proofs")
appendHexBytesArray(b, item.CellProofs)
})
}
}

View file

@ -34,6 +34,8 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
BlockAccessList hexutil.Bytes `json:"blockAccessList,omitempty"`
SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"`
} }
var enc ExecutableData var enc ExecutableData
enc.ParentHash = e.ParentHash enc.ParentHash = e.ParentHash
@ -58,6 +60,8 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
enc.Withdrawals = e.Withdrawals enc.Withdrawals = e.Withdrawals
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed) enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas) enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
enc.BlockAccessList = e.BlockAccessList
enc.SlotNumber = (*hexutil.Uint64)(e.SlotNumber)
return json.Marshal(&enc) return json.Marshal(&enc)
} }
@ -81,6 +85,8 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"` BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"` ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
BlockAccessList *hexutil.Bytes `json:"blockAccessList,omitempty"`
SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"`
} }
var dec ExecutableData var dec ExecutableData
if err := json.Unmarshal(input, &dec); err != nil { if err := json.Unmarshal(input, &dec); err != nil {
@ -154,5 +160,11 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
if dec.ExcessBlobGas != nil { if dec.ExcessBlobGas != nil {
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas) e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
} }
if dec.BlockAccessList != nil {
e.BlockAccessList = *dec.BlockAccessList
}
if dec.SlotNumber != nil {
e.SlotNumber = (*uint64)(dec.SlotNumber)
}
return nil return nil
} }

View file

@ -12,31 +12,6 @@ import (
var _ = (*executionPayloadEnvelopeMarshaling)(nil) var _ = (*executionPayloadEnvelopeMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
type ExecutionPayloadEnvelope struct {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
BlobsBundle *BlobsBundle `json:"blobsBundle"`
Requests []hexutil.Bytes `json:"executionRequests"`
Override bool `json:"shouldOverrideBuilder"`
Witness *hexutil.Bytes `json:"witness,omitempty"`
}
var enc ExecutionPayloadEnvelope
enc.ExecutionPayload = e.ExecutionPayload
enc.BlockValue = (*hexutil.Big)(e.BlockValue)
enc.BlobsBundle = e.BlobsBundle
if e.Requests != nil {
enc.Requests = make([]hexutil.Bytes, len(e.Requests))
for k, v := range e.Requests {
enc.Requests[k] = v
}
}
enc.Override = e.Override
enc.Witness = e.Witness
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON. // UnmarshalJSON unmarshals from JSON.
func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error { func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
type ExecutionPayloadEnvelope struct { type ExecutionPayloadEnvelope struct {

102
beacon/engine/epe_encode.go Normal file
View file

@ -0,0 +1,102 @@
// Copyright 2026 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package engine
import (
"encoding/json"
"errors"
"github.com/fjl/jsonw"
)
// marshalBlobsBundle writes BlobsBundle as JSON and appends it to buf.
func marshalBlobsBundle(b *jsonw.Buffer, bundle *BlobsBundle) {
if bundle == nil {
b.Null()
return
}
b.Object(func() {
b.Key("commitments")
appendHexBytesArray(b, bundle.Commitments)
b.Key("proofs")
appendHexBytesArray(b, bundle.Proofs)
b.Key("blobs")
appendHexBytesArray(b, bundle.Blobs)
})
}
// MarshalJSON implements json.Marshaler.
func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
if e.ExecutionPayload == nil {
return nil, errors.New("missing required field 'executionPayload' for ExecutionPayloadEnvelope")
}
// Pre-marshal the execution payload using its gencodec MarshalJSON.
payload, err := e.ExecutionPayload.MarshalJSON()
if err != nil {
return nil, err
}
// Pre-marshal the witness.
var witness []byte
if e.Witness != nil {
witness, err = json.Marshal(e.Witness)
if err != nil {
return nil, err
}
}
// Write the execution payload to the buffer
var b jsonw.Buffer
b.Object(func() {
b.Key("executionPayload")
b.RawValue(payload)
b.Key("blockValue")
if e.BlockValue != nil {
b.HexBigInt(e.BlockValue)
} else {
b.Null()
}
b.Key("blobsBundle")
marshalBlobsBundle(&b, e.BlobsBundle)
b.Key("executionRequests")
if e.Requests == nil {
b.Null()
} else {
appendHexBytesArray(&b, e.Requests)
}
b.Key("shouldOverrideBuilder")
b.Bool(e.Override)
if e.Witness != nil {
b.Key("witness")
b.RawValue(witness)
}
})
return b.Output(), nil
}
func appendHexBytesArray[T ~[]byte](b *jsonw.Buffer, slice []T) {
b.Array(func() {
for _, elem := range slice {
b.HexBytes(elem)
}
})
}

128
beacon/engine/epe_test.go Normal file
View file

@ -0,0 +1,128 @@
// Copyright 2026 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package engine
import (
"bytes"
"encoding/json"
"math/big"
"reflect"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
func makeTestPayload() *ExecutableData {
return &ExecutableData{
ParentHash: common.HexToHash("0x01"),
FeeRecipient: common.HexToAddress("0x02"),
StateRoot: common.HexToHash("0x03"),
ReceiptsRoot: common.HexToHash("0x04"),
LogsBloom: make([]byte, 256),
Random: common.HexToHash("0x05"),
Number: 100,
GasLimit: 1000000,
GasUsed: 500000,
Timestamp: 1234567890,
ExtraData: []byte("extra"),
BaseFeePerGas: big.NewInt(7),
BlockHash: common.HexToHash("0x08"),
Transactions: [][]byte{{0xaa, 0xbb}},
}
}
func TestMarshalJSONRoundtrip(t *testing.T) {
witness := hexutil.Bytes{0xde, 0xad}
original := ExecutionPayloadEnvelope{
ExecutionPayload: makeTestPayload(),
BlockValue: big.NewInt(12345),
BlobsBundle: &BlobsBundle{
Commitments: []hexutil.Bytes{{0x01, 0x02}},
Proofs: []hexutil.Bytes{{0x03, 0x04}},
Blobs: []hexutil.Bytes{{0x05, 0x06}},
},
Requests: [][]byte{{0xaa}, {0xbb, 0xcc}},
Override: true,
Witness: &witness,
}
data, err := original.MarshalJSON()
if err != nil {
t.Fatalf("MarshalJSON error: %v", err)
}
var decoded ExecutionPayloadEnvelope
if err := json.Unmarshal(data, &decoded); err != nil {
t.Fatalf("UnmarshalJSON error: %v", err)
}
if decoded.ExecutionPayload.Number != original.ExecutionPayload.Number {
t.Error("ExecutionPayload.Number mismatch")
}
if decoded.BlockValue.Cmp(original.BlockValue) != 0 {
t.Errorf("BlockValue mismatch: got %v, want %v", decoded.BlockValue, original.BlockValue)
}
if len(decoded.BlobsBundle.Blobs) != len(original.BlobsBundle.Blobs) {
t.Error("BlobsBundle.Blobs length mismatch")
}
if len(decoded.Requests) != len(original.Requests) {
t.Error("Requests length mismatch")
}
if decoded.Override != original.Override {
t.Error("Override mismatch")
}
if !bytes.Equal(*decoded.Witness, *original.Witness) {
t.Error("Witness mismatch")
}
}
func TestMarshalJSONNilPayload(t *testing.T) {
env := ExecutionPayloadEnvelope{
ExecutionPayload: nil,
BlockValue: big.NewInt(1),
}
_, err := env.MarshalJSON()
if err == nil {
t.Fatal("expected error for nil ExecutionPayload")
}
}
// TestExecutionPayloadEnvelopeFieldCoverage guards against structural drift.
// If a field is added to or removed from ExecutionPayloadEnvelope, this test
// fails, reminding the developer to update MarshalJSON in marshal_epe.go.
func TestExecutionPayloadEnvelopeFieldCoverage(t *testing.T) {
expected := []string{
"ExecutionPayload",
"BlockValue",
"BlobsBundle",
"Requests",
"Override",
"Witness",
}
typ := reflect.TypeOf(ExecutionPayloadEnvelope{})
if typ.NumField() != len(expected) {
t.Fatalf("ExecutionPayloadEnvelope has %d fields, expected %d — update MarshalJSON in marshal_epe.go",
typ.NumField(), len(expected))
}
for i, name := range expected {
if typ.Field(i).Name != name {
t.Errorf("field %d: got %q, want %q — update MarshalJSON in marshal_epe.go",
i, typ.Field(i).Name, name)
}
}
}

View file

@ -81,6 +81,7 @@ var (
TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"} TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"}
InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"} InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"}
UnsupportedFork = &EngineAPIError{code: -38005, msg: "Unsupported fork"} UnsupportedFork = &EngineAPIError{code: -38005, msg: "Unsupported fork"}
TooDeepReorg = &EngineAPIError{code: -38006, msg: "Too deep reorg"}
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil} STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil} STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}

View file

@ -21,6 +21,8 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
SlotNumber *hexutil.Uint64 `json:"slotNumber"`
TargetGasLimit *hexutil.Uint64 `json:"targetGasLimit"`
} }
var enc PayloadAttributes var enc PayloadAttributes
enc.Timestamp = hexutil.Uint64(p.Timestamp) enc.Timestamp = hexutil.Uint64(p.Timestamp)
@ -28,6 +30,8 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
enc.Withdrawals = p.Withdrawals enc.Withdrawals = p.Withdrawals
enc.BeaconRoot = p.BeaconRoot enc.BeaconRoot = p.BeaconRoot
enc.SlotNumber = (*hexutil.Uint64)(p.SlotNumber)
enc.TargetGasLimit = (*hexutil.Uint64)(p.TargetGasLimit)
return json.Marshal(&enc) return json.Marshal(&enc)
} }
@ -39,6 +43,8 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"` SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
SlotNumber *hexutil.Uint64 `json:"slotNumber"`
TargetGasLimit *hexutil.Uint64 `json:"targetGasLimit"`
} }
var dec PayloadAttributes var dec PayloadAttributes
if err := json.Unmarshal(input, &dec); err != nil { if err := json.Unmarshal(input, &dec); err != nil {
@ -62,5 +68,11 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
if dec.BeaconRoot != nil { if dec.BeaconRoot != nil {
p.BeaconRoot = dec.BeaconRoot p.BeaconRoot = dec.BeaconRoot
} }
if dec.SlotNumber != nil {
p.SlotNumber = (*uint64)(dec.SlotNumber)
}
if dec.TargetGasLimit != nil {
p.TargetGasLimit = (*uint64)(dec.TargetGasLimit)
}
return nil return nil
} }

View file

@ -17,6 +17,7 @@
package engine package engine
import ( import (
"bytes"
"fmt" "fmt"
"math/big" "math/big"
"slices" "slices"
@ -24,7 +25,10 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types/bal"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
@ -50,9 +54,16 @@ var (
// ExecutionPayloadV3 has the syntax of ExecutionPayloadV2 and appends the new // ExecutionPayloadV3 has the syntax of ExecutionPayloadV2 and appends the new
// fields: blobGasUsed and excessBlobGas. // fields: blobGasUsed and excessBlobGas.
PayloadV3 PayloadVersion = 0x3 PayloadV3 PayloadVersion = 0x3
// PayloadV4 is the identifier of ExecutionPayloadV4 introduced in amsterdam fork.
//
// https://github.com/ethereum/execution-apis/blob/main/src/engine/amsterdam.md#executionpayloadv4
// ExecutionPayloadV4 has the syntax of ExecutionPayloadV3 and appends the new
// fields slotNumber and blockAccessList.
PayloadV4 PayloadVersion = 0x4
) )
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go //go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out pa_codec.go
// PayloadAttributes describes the environment context in which a block should // PayloadAttributes describes the environment context in which a block should
// be built. // be built.
@ -62,14 +73,18 @@ type PayloadAttributes struct {
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
SlotNumber *uint64 `json:"slotNumber"`
TargetGasLimit *uint64 `json:"targetGasLimit"`
} }
// JSON type overrides for PayloadAttributes. // JSON type overrides for PayloadAttributes.
type payloadAttributesMarshaling struct { type payloadAttributesMarshaling struct {
Timestamp hexutil.Uint64 Timestamp hexutil.Uint64
SlotNumber *hexutil.Uint64
TargetGasLimit *hexutil.Uint64
} }
//go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go //go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out ed_codec.go
// ExecutableData is the data necessary to execute an EL payload. // ExecutableData is the data necessary to execute an EL payload.
type ExecutableData struct { type ExecutableData struct {
@ -90,6 +105,8 @@ type ExecutableData struct {
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
BlobGasUsed *uint64 `json:"blobGasUsed"` BlobGasUsed *uint64 `json:"blobGasUsed"`
ExcessBlobGas *uint64 `json:"excessBlobGas"` ExcessBlobGas *uint64 `json:"excessBlobGas"`
BlockAccessList []byte `json:"blockAccessList,omitempty"`
SlotNumber *uint64 `json:"slotNumber,omitempty"`
} }
// JSON type overrides for executableData. // JSON type overrides for executableData.
@ -104,6 +121,8 @@ type executableDataMarshaling struct {
Transactions []hexutil.Bytes Transactions []hexutil.Bytes
BlobGasUsed *hexutil.Uint64 BlobGasUsed *hexutil.Uint64
ExcessBlobGas *hexutil.Uint64 ExcessBlobGas *hexutil.Uint64
SlotNumber *hexutil.Uint64
BlockAccessList hexutil.Bytes
} }
// StatelessPayloadStatusV1 is the result of a stateless payload execution. // StatelessPayloadStatusV1 is the result of a stateless payload execution.
@ -114,7 +133,7 @@ type StatelessPayloadStatusV1 struct {
ValidationError *string `json:"validationError"` ValidationError *string `json:"validationError"`
} }
//go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go //go:generate go run github.com/fjl/gencodec -enc=false -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out epe_decode.go
type ExecutionPayloadEnvelope struct { type ExecutionPayloadEnvelope struct {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
@ -125,6 +144,12 @@ type ExecutionPayloadEnvelope struct {
Witness *hexutil.Bytes `json:"witness,omitempty"` Witness *hexutil.Bytes `json:"witness,omitempty"`
} }
// JSON type overrides for ExecutionPayloadEnvelope.
type executionPayloadEnvelopeMarshaling struct {
BlockValue *hexutil.Big
Requests []hexutil.Bytes
}
// BlobsBundle includes the marshalled sidecar data. Note this structure is // BlobsBundle includes the marshalled sidecar data. Note this structure is
// shared by BlobsBundleV1 and BlobsBundleV2 for the sake of simplicity. // shared by BlobsBundleV1 and BlobsBundleV2 for the sake of simplicity.
// //
@ -141,17 +166,24 @@ type BlobAndProofV1 struct {
Proof hexutil.Bytes `json:"proof"` Proof hexutil.Bytes `json:"proof"`
} }
// BlobAndProofListV1 is a list of BlobAndProofV1 with a hand-rolled JSON marshaler
// that avoids the overhead of encoding/json for large blob payloads.
type BlobAndProofListV1 []*BlobAndProofV1
type BlobAndProofV2 struct { type BlobAndProofV2 struct {
Blob hexutil.Bytes `json:"blob"` Blob hexutil.Bytes `json:"blob"`
CellProofs []hexutil.Bytes `json:"proofs"` // proofs MUST contain exactly CELLS_PER_EXT_BLOB cell proofs. CellProofs []hexutil.Bytes `json:"proofs"` // proofs MUST contain exactly CELLS_PER_EXT_BLOB cell proofs.
} }
// JSON type overrides for ExecutionPayloadEnvelope. type BlobCellsAndProofsV1 struct {
type executionPayloadEnvelopeMarshaling struct { BlobCells []*hexutil.Bytes `json:"blob_cells"`
BlockValue *hexutil.Big Proofs []*hexutil.Bytes `json:"proofs"`
Requests []hexutil.Bytes
} }
// BlobAndProofListV2 is a list of BlobAndProofV2 with a hand-rolled JSON marshaler
// that avoids the overhead of encoding/json for large blob payloads.
type BlobAndProofListV2 []*BlobAndProofV2
type PayloadStatusV1 struct { type PayloadStatusV1 struct {
Status string `json:"status"` Status string `json:"status"`
Witness *hexutil.Bytes `json:"witness,omitempty"` Witness *hexutil.Bytes `json:"witness,omitempty"`
@ -213,7 +245,7 @@ func encodeTransactions(txs []*types.Transaction) [][]byte {
return enc return enc
} }
func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) { func DecodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
var txs = make([]*types.Transaction, len(enc)) var txs = make([]*types.Transaction, len(enc))
for i, encTx := range enc { for i, encTx := range enc {
var tx types.Transaction var tx types.Transaction
@ -251,7 +283,7 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
// for stateless execution, so it skips checking if the executable data hashes to // for stateless execution, so it skips checking if the executable data hashes to
// the requested hash (stateless has to *compute* the root hash, it's not given). // the requested hash (stateless has to *compute* the root hash, it's not given).
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) { func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) {
txs, err := decodeTransactions(data.Transactions) txs, err := DecodeTransactions(data.Transactions)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -265,7 +297,7 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
if data.BaseFeePerGas != nil && (data.BaseFeePerGas.Sign() == -1 || data.BaseFeePerGas.BitLen() > 256) { if data.BaseFeePerGas != nil && (data.BaseFeePerGas.Sign() == -1 || data.BaseFeePerGas.BitLen() > 256) {
return nil, fmt.Errorf("invalid baseFeePerGas: %v", data.BaseFeePerGas) return nil, fmt.Errorf("invalid baseFeePerGas: %v", data.BaseFeePerGas)
} }
var blobHashes = make([]common.Hash, 0, len(txs)) var blobHashes = make([]common.Hash, 0, len(versionedHashes))
for _, tx := range txs { for _, tx := range txs {
blobHashes = append(blobHashes, tx.BlobHashes()...) blobHashes = append(blobHashes, tx.BlobHashes()...)
} }
@ -274,7 +306,7 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
} }
for i := 0; i < len(blobHashes); i++ { for i := 0; i < len(blobHashes); i++ {
if blobHashes[i] != versionedHashes[i] { if blobHashes[i] != versionedHashes[i] {
return nil, fmt.Errorf("invalid versionedHash at %v: %v blobHashes: %v", i, versionedHashes, blobHashes) return nil, fmt.Errorf("invalid versionedHash at %v: %v blobHash: %v", i, versionedHashes[i], blobHashes[i])
} }
} }
// Only set withdrawalsRoot if it is non-nil. This allows CLs to use // Only set withdrawalsRoot if it is non-nil. This allows CLs to use
@ -292,6 +324,16 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
requestsHash = &h requestsHash = &h
} }
// If Amsterdam is enabled, data.BlockAccessList is always non-nil,
// even for empty blocks with no state transitions.
//
// If Amsterdam is not enabled yet, blockAccessListHash is expected
// to be nil.
var blockAccessListHash *common.Hash
if data.BlockAccessList != nil {
hash := crypto.Keccak256Hash(data.BlockAccessList)
blockAccessListHash = &hash
}
header := &types.Header{ header := &types.Header{
ParentHash: data.ParentHash, ParentHash: data.ParentHash,
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
@ -313,10 +355,18 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
BlobGasUsed: data.BlobGasUsed, BlobGasUsed: data.BlobGasUsed,
ParentBeaconRoot: beaconRoot, ParentBeaconRoot: beaconRoot,
RequestsHash: requestsHash, RequestsHash: requestsHash,
SlotNumber: data.SlotNumber,
BlockAccessListHash: blockAccessListHash,
} }
return types.NewBlockWithHeader(header). body := types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}), if data.BlockAccessList != nil {
nil var accessList bal.BlockAccessList
if err := rlp.DecodeBytes(data.BlockAccessList, &accessList); err != nil {
return nil, fmt.Errorf("failed to decode BAL: %w", err)
}
return types.NewBlockWithHeader(header).WithBody(body).WithAccessListUnsafe(&accessList), nil
}
return types.NewBlockWithHeader(header).WithBody(body), nil
} }
// BlockToExecutableData constructs the ExecutableData structure by filling the // BlockToExecutableData constructs the ExecutableData structure by filling the
@ -340,6 +390,13 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
Withdrawals: block.Withdrawals(), Withdrawals: block.Withdrawals(),
BlobGasUsed: block.BlobGasUsed(), BlobGasUsed: block.BlobGasUsed(),
ExcessBlobGas: block.ExcessBlobGas(), ExcessBlobGas: block.ExcessBlobGas(),
SlotNumber: block.SlotNumber(),
}
if al := block.AccessList(); al != nil {
var buf bytes.Buffer
if err := rlp.Encode(&buf, al); err == nil {
data.BlockAccessList = buf.Bytes()
}
} }
// Add blobs. // Add blobs.
@ -382,6 +439,12 @@ type ExecutionPayloadBody struct {
Withdrawals []*types.Withdrawal `json:"withdrawals"` Withdrawals []*types.Withdrawal `json:"withdrawals"`
} }
// ExecutionPayloadBodyV2 extends ExecutionPayloadBody with the block access list.
type ExecutionPayloadBodyV2 struct {
ExecutionPayloadBody
BlockAccessList *hexutil.Bytes `json:"blockAccessList"`
}
// Client identifiers to support ClientVersionV1. // Client identifiers to support ClientVersionV1.
const ( const (
ClientCode = "GE" ClientCode = "GE"

View file

@ -182,6 +182,12 @@ func (s *CommitteeChain) Reset() {
s.chainmu.Lock() s.chainmu.Lock()
defer s.chainmu.Unlock() defer s.chainmu.Unlock()
s.resetLocked()
}
// ResetLocked resets the committee chain without locking. The caller should hold
// the chainmu lock.
func (s *CommitteeChain) resetLocked() {
if err := s.rollback(0); err != nil { if err := s.rollback(0); err != nil {
log.Error("Error writing batch into chain database", "error", err) log.Error("Error writing batch into chain database", "error", err)
} }
@ -201,22 +207,22 @@ func (s *CommitteeChain) CheckpointInit(bootstrap types.BootstrapData) error {
} }
period := bootstrap.Header.SyncPeriod() period := bootstrap.Header.SyncPeriod()
if err := s.deleteFixedCommitteeRootsFrom(period + 2); err != nil { if err := s.deleteFixedCommitteeRootsFrom(period + 2); err != nil {
s.Reset() s.resetLocked()
return err return err
} }
if s.addFixedCommitteeRoot(period, bootstrap.CommitteeRoot) != nil { if s.addFixedCommitteeRoot(period, bootstrap.CommitteeRoot) != nil {
s.Reset() s.resetLocked()
if err := s.addFixedCommitteeRoot(period, bootstrap.CommitteeRoot); err != nil { if err := s.addFixedCommitteeRoot(period, bootstrap.CommitteeRoot); err != nil {
s.Reset() s.resetLocked()
return err return err
} }
} }
if err := s.addFixedCommitteeRoot(period+1, common.Hash(bootstrap.CommitteeBranch[0])); err != nil { if err := s.addFixedCommitteeRoot(period+1, common.Hash(bootstrap.CommitteeBranch[0])); err != nil {
s.Reset() s.resetLocked()
return err return err
} }
if err := s.addCommittee(period, bootstrap.Committee); err != nil { if err := s.addCommittee(period, bootstrap.Committee); err != nil {
s.Reset() s.resetLocked()
return err return err
} }
s.changeCounter++ s.changeCounter++

View file

@ -438,14 +438,11 @@ func (s *serverWithLimits) fail(desc string) {
// failLocked calculates the dynamic failure delay and applies it. // failLocked calculates the dynamic failure delay and applies it.
func (s *serverWithLimits) failLocked(desc string) { func (s *serverWithLimits) failLocked(desc string) {
log.Debug("Server error", "description", desc) log.Debug("Server error", "description", desc)
s.failureDelay *= 2
now := s.clock.Now() now := s.clock.Now()
if now > s.failureDelayEnd { if now > s.failureDelayEnd {
s.failureDelay *= math.Pow(2, -float64(now-s.failureDelayEnd)/float64(maxFailureDelay)) s.failureDelay *= math.Pow(2, -float64(now-s.failureDelayEnd)/float64(maxFailureDelay))
} }
if s.failureDelay < float64(minFailureDelay) { s.failureDelay = max(min(s.failureDelay*2, float64(maxFailureDelay)), float64(minFailureDelay))
s.failureDelay = float64(minFailureDelay)
}
s.failureDelayEnd = now + mclock.AbsTime(s.failureDelay) s.failureDelayEnd = now + mclock.AbsTime(s.failureDelay)
s.delay(time.Duration(s.failureDelay)) s.delay(time.Duration(s.failureDelay))
} }

View file

@ -62,7 +62,6 @@ const (
ssNeedParent // cp header slot %32 != 0, need parent to check epoch boundary ssNeedParent // cp header slot %32 != 0, need parent to check epoch boundary
ssParentRequested // cp parent header requested ssParentRequested // cp parent header requested
ssPrintStatus // has all necessary info, print log message if init still not successful ssPrintStatus // has all necessary info, print log message if init still not successful
ssDone // log message printed, no more action required
) )
type serverState struct { type serverState struct {
@ -99,7 +98,10 @@ func (s *CheckpointInit) Process(requester request.Requester, events []request.E
case ssDefault: case ssDefault:
if resp != nil { if resp != nil {
if checkpoint := resp.(*types.BootstrapData); checkpoint.Header.Hash() == common.Hash(req.(ReqCheckpointData)) { if checkpoint := resp.(*types.BootstrapData); checkpoint.Header.Hash() == common.Hash(req.(ReqCheckpointData)) {
s.chain.CheckpointInit(*checkpoint) err := s.chain.CheckpointInit(*checkpoint)
if err != nil {
return
}
s.initialized = true s.initialized = true
return return
} }
@ -180,7 +182,8 @@ func (s *CheckpointInit) Process(requester request.Requester, events []request.E
default: default:
log.Error("blsync: checkpoint not available, but reported as finalized; specified checkpoint hash might be too old", "server", server.Name()) log.Error("blsync: checkpoint not available, but reported as finalized; specified checkpoint hash might be too old", "server", server.Name())
} }
s.serverState[server] = serverState{state: ssDone} s.serverState[server] = serverState{state: ssDefault}
requester.Fail(server, "checkpoint init failed")
} }
} }

View file

@ -1,85 +1,106 @@
# This file contains sha256 checksums of optional build dependencies. # This file contains sha256 checksums of optional build dependencies.
# version:spec-tests v5.1.0 # version:spec-tests tests@v20.0.0
# https://github.com/ethereum/execution-spec-tests/releases # https://github.com/ethereum/execution-specs/releases
# https://github.com/ethereum/execution-spec-tests/releases/download/v5.1.0 # https://github.com/ethereum/execution-specs/releases/download/tests%40v20.0.0
a3192784375acec7eaec492799d5c5d0c47a2909a3cc40178898e4ecd20cc416 fixtures_develop.tar.gz b183702a5b447b465873865357ced9eb342315922e52e31b714e2de115dd0bb4 fixtures.tar.gz
# version:golang 1.25.1 # version:golang 1.25.12
# https://go.dev/dl/ # https://go.dev/dl/
d010c109cee94d80efe681eab46bdea491ac906bf46583c32e9f0dbb0bd1a594 go1.25.1.src.tar.gz f90dcee4bd023fa376374ea0a5a6ebe553537b39c426ffd8c689469b45519932 go1.25.12.src.tar.gz
1d622468f767a1b9fe1e1e67bd6ce6744d04e0c68712adc689748bbeccb126bb go1.25.1.darwin-amd64.tar.gz 70b4b6509ed60735eff6ed9496824ad9f96201fdf5bd190184123f5908f224ef go1.25.12.aix-ppc64.tar.gz
68deebb214f39d542e518ebb0598a406ab1b5a22bba8ec9ade9f55fb4dd94a6c go1.25.1.darwin-arm64.tar.gz 00a2e743b82bccec03c51c4b0f7e46d5fec52184075fd6c5183c3bb39ae9fb00 go1.25.12.darwin-amd64.tar.gz
d03cdcbc9bd8baf5cf028de390478e9e2b3e4d0afe5a6582dedc19bfe6a263b2 go1.25.1.linux-386.tar.gz fa2c88bbcf64bd3b2aef355f026cfec6d3a4a01c132f999c8f8c964eb767164f go1.25.12.darwin-arm64.tar.gz
7716a0d940a0f6ae8e1f3b3f4f36299dc53e31b16840dbd171254312c41ca12e go1.25.1.linux-amd64.tar.gz 2124cfbc1cf0b949eb819478365d4d665f84297a60f327cc65f75f61b2629b96 go1.25.12.dragonfly-amd64.tar.gz
65a3e34fb2126f55b34e1edfc709121660e1be2dee6bdf405fc399a63a95a87d go1.25.1.linux-arm64.tar.gz bdb8ab506428e9633653e67c13d582a6230406f01037023b327427c66b058ff2 go1.25.12.freebsd-386.tar.gz
eb949be683e82a99e9861dafd7057e31ea40b161eae6c4cd18fdc0e8c4ae6225 go1.25.1.linux-armv6l.tar.gz 4433a424d466d47d1716df69e6a77c65b1a34d82121488014e4656d73740ebb0 go1.25.12.freebsd-amd64.tar.gz
be13d5479b8c75438f2efcaa8c191fba3af684b3228abc9c99c7aa8502f34424 go1.25.1.windows-386.zip 429fbcb46468a66d1cd24129a1b6163167676aaae8e0989a08ba95ba6aae65c4 go1.25.12.freebsd-arm.tar.gz
4a974de310e7ee1d523d2fcedb114ba5fa75408c98eb3652023e55ccf3fa7cab go1.25.1.windows-amd64.zip c0e31a4cb827fd20fac950bcb4688fd94cdd1491dbdcff7c3754ac8f3b136eb1 go1.25.12.freebsd-arm64.tar.gz
45ab4290adbd6ee9e7f18f0d57eaa9008fdbef590882778ed93eac3c8cca06c5 go1.25.1.aix-ppc64.tar.gz 0ea50c6d43e809d46c2c5504e97ef11822f7ca137625171924cda971449b5373 go1.25.12.freebsd-riscv64.tar.gz
2e3c1549bed3124763774d648f291ac42611232f48320ebbd23517c909c09b81 go1.25.1.dragonfly-amd64.tar.gz d74c214e0c3ae8f9db23f4ec6f6b2f6cb300c3e4b9d840b82fa517af629c455d go1.25.12.illumos-amd64.tar.gz
dc0198dd4ec520e13f26798def8750544edf6448d8e9c43fd2a814e4885932af go1.25.1.freebsd-386.tar.gz b71e88ae779850dc2afcd0f2e2208798652311dfda72fdef5d05721d601b8fd3 go1.25.12.linux-386.tar.gz
c4f1a7e7b258406e6f3b677ecdbd97bbb23ff9c0d44be4eb238a07d360f69ac8 go1.25.1.freebsd-amd64.tar.gz 234828b7a89e0e303d2556310ee549fbcf253d28de937bac3da13d6294262ac1 go1.25.12.linux-amd64.tar.gz
7772fc5ff71ed39297ec0c1599fc54e399642c9b848eac989601040923b0de9c go1.25.1.freebsd-arm.tar.gz 8b5884aef89600aef5b0b051fb971f11f49bb996521e911f30f02a66884f7bd2 go1.25.12.linux-arm64.tar.gz
5bb011d5d5b6218b12189f07aa0be618ab2002662fff1ca40afba7389735c207 go1.25.1.freebsd-arm64.tar.gz 6cd7311c02c73ba0b482a1cf8c885268edf23519261bf4b5cef3353ad934d1f1 go1.25.12.linux-armv6l.tar.gz
ccac716240cb049bebfafcb7eebc3758512178a4c51fc26da9cc032035d850c8 go1.25.1.freebsd-riscv64.tar.gz 0c6b2b7db8509d1df189433709ddc8fe84c12843e3713508e9ca04dc9e75ddeb go1.25.12.linux-loong64.tar.gz
cc53910ffb9fcfdd988a9fa25b5423bae1cfa01b19616be646700e1f5453b466 go1.25.1.illumos-amd64.tar.gz 5abc63471425ab8b3408f596cd547d28d374f6dc860a4cbd6de79497123db4f3 go1.25.12.linux-mips.tar.gz
efe809f923bcedab44bf7be2b3af8d182b512b1bf9c07d302e0c45d26c8f56f3 go1.25.1.linux-loong64.tar.gz a18f7a5ac799ed8ac264b63707e7fa475b1b81da6bbdd41c394fcfd69cc6b736 go1.25.12.linux-mips64.tar.gz
c0de33679f6ed68991dc42dc4a602e74a666e3e166c1748ee1b5d1a7ea2ffbb2 go1.25.1.linux-mips.tar.gz 5bde8a5d4c05b428fca3e6022dc41d4c735858be9c6945e57473da00fcddd0cc go1.25.12.linux-mips64le.tar.gz
c270f7b0c0bdfbcd54fef4481227c40d41bb518f9ae38ee930870f04a0a6a589 go1.25.1.linux-mips64.tar.gz 33c243d2b0700589e75a410ebab5b64580a477e908872abc46eef840e6ea535a go1.25.12.linux-mipsle.tar.gz
80be871ba9c944f34d1868cdf5047e1cf2e1289fe08cdb90e2453d2f0d6965ae go1.25.1.linux-mips64le.tar.gz b5288a7adb38540177146b47aa43bc75f1936c5e14026d6b6e531b534a49eb1a go1.25.12.linux-ppc64.tar.gz
9f09defa9bb22ebf2cde76162f40958564e57ce5c2b3649bc063bebcbc9294c1 go1.25.1.linux-mipsle.tar.gz 64adb4ddefef4f0a6f11af550547f39bf510350da69ab308438a21eacfde97ad go1.25.12.linux-ppc64le.tar.gz
2c76b7d278c1d43ad19d478ad3f0f05e7b782b64b90870701b314fa48b5f43c6 go1.25.1.linux-ppc64.tar.gz 26919d62d21b0bee9c5c67ad76ace462edd16c2c128a983d942cb45b0bf7693c go1.25.12.linux-riscv64.tar.gz
8b0c8d3ee5b1b5c28b6bd63dc4438792012e01d03b4bf7a61d985c87edab7d1f go1.25.1.linux-ppc64le.tar.gz 09875de1d6cb3237437112271b9df3a96bac9fcd10cbf9bc777c00e67f4e3e3d go1.25.12.linux-s390x.tar.gz
22fe934a9d0c9c57275716c55b92d46ebd887cec3177c9140705efa9f84ba1e2 go1.25.1.linux-riscv64.tar.gz 2f19f4afc3d6551804228484569ec1ebf4a57a91cda75d746384aa71d5016be7 go1.25.12.netbsd-386.tar.gz
9cfe517ba423f59f3738ca5c3d907c103253cffbbcc2987142f79c5de8c1bf93 go1.25.1.linux-s390x.tar.gz d2237237d34058658187455d4f05f8f4f5f2118b33827308ad8313ab0f00a693 go1.25.12.netbsd-amd64.tar.gz
6af8a08353e76205d5b743dd7a3f0126684f96f62be0a31b75daf9837e512c46 go1.25.1.netbsd-386.tar.gz 4d44c8141a829541c3499db6665a47be2c6fdb97903575058809a2a8be53af89 go1.25.12.netbsd-arm.tar.gz
e5d534ff362edb1bd8c8e10892b6a027c4c1482454245d1529167676498684c7 go1.25.1.netbsd-amd64.tar.gz fc96791f8b9cdaea544e827dc15574731afd28b7378053e801b3bd466df6dd9d go1.25.12.netbsd-arm64.tar.gz
88bcf39254fdcea6a199c1c27d787831b652427ce60851ae9e41a3d7eb477f45 go1.25.1.netbsd-arm.tar.gz e9ced39c191409207a211c6013b9a156bd90dbd5a76ebd8c66dc3bf69bcb2f9e go1.25.12.openbsd-386.tar.gz
d7c2eabe1d04ee47bcaea2816fdd90dbd25d90d4dfa756faa9786c788e4f3a4e go1.25.1.netbsd-arm64.tar.gz bae7c016f0aff806c9af08ecff96b59a232144c96b1d25f4c5f6c85c8e0dbf01 go1.25.12.openbsd-amd64.tar.gz
14a2845977eb4dde11d929858c437a043467c427db87899935e90cee04a38d72 go1.25.1.openbsd-386.tar.gz 8517c4bca20e975acdd5a2f5e425cd2bec737bbb6d7ee18d11e3a1545014267e go1.25.12.openbsd-arm.tar.gz
d27ac54b38a13a09c81e67c82ac70d387037341c85c3399291c73e13e83fdd8c go1.25.1.openbsd-amd64.tar.gz ba4ac29243f43b85a52f12ed7dd02b767e4524785fb6d04fececb7ce125aaa82 go1.25.12.openbsd-arm64.tar.gz
0f4ab5f02500afa4befd51fed1e8b45e4d07ca050f641cc3acc76eaa4027b2c3 go1.25.1.openbsd-arm.tar.gz dca067f41d00ba805342062ab21b88831a06a5682e9aaec1c990c175a5656c6b go1.25.12.openbsd-ppc64.tar.gz
d46c3bd156843656f7f3cb0dec27ea51cd926ec3f7b80744bf8156e67c1c812f go1.25.1.openbsd-arm64.tar.gz 4f1f5376464fc91f32cd253dadfe3535ff57d1729b24e6ab014fb83964dfe10f go1.25.12.openbsd-riscv64.tar.gz
c550514c67f22e409be10e40eace761e2e43069f4ef086ae6e60aac736c2b679 go1.25.1.openbsd-ppc64.tar.gz c938792ec65ba33592deea6673265d509aaf9b5297119bc91ae973fb6beb62b9 go1.25.12.plan9-386.tar.gz
8a09a8714a2556eb13fc1f10b7ce2553fcea4971e3330fc3be0efd24aab45734 go1.25.1.openbsd-riscv64.tar.gz 5aec7ab115c1c6cd049a64f1617ef91d24ea07c8b0f40436d531b42d546f5e37 go1.25.12.plan9-amd64.tar.gz
b0e1fefaf0c7abd71f139a54eee9767944aff5f0bc9d69c968234804884e552f go1.25.1.plan9-386.tar.gz efe1dcb9750507260a28688a749c72f35c3160646f08a80606f38c3d30d74a12 go1.25.12.plan9-arm.tar.gz
e94732c94f149690aa0ab11c26090577211b4a988137cb2c03ec0b54e750402e go1.25.1.plan9-amd64.tar.gz 83c42cfedcc0bb03fd601d692d75b085406c9a7f5ff505bf41030f2734b62ed2 go1.25.12.solaris-amd64.tar.gz
7eb80e9de1e817d9089a54e8c7c5c8d8ed9e5fb4d4a012fc0f18fc422a484f0c go1.25.1.plan9-arm.tar.gz 18abdf76719f5f84eaa35eeaf87b467a02ed075a8632ad941f10aa7a3d0de713 go1.25.12.windows-386.zip
1261dfad7c4953c0ab90381bc1242dc54e394db7485c59349428d532b2273343 go1.25.1.solaris-amd64.tar.gz d5dc82da351b00e5eedd04f41356817d674cc4308131f0f638a5b14c5c3af4cb go1.25.12.windows-amd64.zip
04bc3c078e9e904c4d58d6ac2532a5bdd402bd36a9ff0b5949b3c5e6006a05ee go1.25.1.windows-arm64.zip 054f046a5fa31fdcc9491cc19065cbf43bf521d805bbe298ae8d65dd981fca84 go1.25.12.windows-arm64.zip
# version:golangci 2.4.0 # version:golangci 2.10.1
# https://github.com/golangci/golangci-lint/releases/ # https://github.com/golangci/golangci-lint/releases/
# https://github.com/golangci/golangci-lint/releases/download/v2.4.0/ # https://github.com/golangci/golangci-lint/releases/download/v2.10.1
7904ce63f79db44934939cf7a063086ea0ea98e9b19eba0a9d52ccdd0d21951c golangci-lint-2.4.0-darwin-amd64.tar.gz 66fb0da81b8033b477f97eea420d4b46b230ca172b8bb87c6610109f3772b6b6 golangci-lint-2.10.1-darwin-amd64.tar.gz
cd4dd53fa09b6646baff5fd22b8c64d91db02c21c7496df27992d75d34feec59 golangci-lint-2.4.0-darwin-arm64.tar.gz 03bfadf67e52b441b7ec21305e501c717df93c959836d66c7f97312654acb297 golangci-lint-2.10.1-darwin-arm64.tar.gz
d58f426ebe14cc257e81562b4bf37a488ffb4ffbbb3ec73041eb3b38bb25c0e1 golangci-lint-2.4.0-freebsd-386.tar.gz c9a44658ccc8f7b8dbbd4ae6020ba91c1a5d3987f4d91ced0f7d2bea013e57ca golangci-lint-2.10.1-freebsd-386.tar.gz
6ec4a6177fc6c0dd541fbcb3a7612845266d020d35cc6fa92959220cdf64ca39 golangci-lint-2.4.0-freebsd-amd64.tar.gz a513c5cb4e0f5bd5767001af9d5e97e7868cfc2d9c46739a4df93e713cfb24af golangci-lint-2.10.1-freebsd-amd64.tar.gz
4d473e3e71c01feaa915a0604fb35758b41284fb976cdeac3f842118d9ee7e17 golangci-lint-2.4.0-freebsd-armv6.tar.gz 2ef38eefc4b5cee2febacb75a30579526e5656c16338a921d80e59a8e87d4425 golangci-lint-2.10.1-freebsd-arm64.tar.gz
58727746c6530801a3f9a702a5945556a5eb7e88809222536dd9f9d54cafaeff golangci-lint-2.4.0-freebsd-armv7.tar.gz 8fea6766318b4829e766bbe325f10191d75297dcc44ae35bf374816037878e38 golangci-lint-2.10.1-freebsd-armv6.tar.gz
fbf28c662760e24c32f82f8d16dffdb4a82de7726a52ba1fad94f890c22997ea golangci-lint-2.4.0-illumos-amd64.tar.gz 30b629870574d6254f3e8804e5a74b34f98e1263c9d55465830d739c88b862ed golangci-lint-2.10.1-freebsd-armv7.tar.gz
a15a000a8981ef665e971e0f67e2acda9066a9e37a59344393b7351d8fb49c81 golangci-lint-2.4.0-linux-386.tar.gz c0db839f866ce80b1b6c96167aa101cfe50d9c936f42d942a3c1cbdc1801af68 golangci-lint-2.10.1-illumos-amd64.tar.gz
fae792524c04424c0ac369f5b8076f04b45cf29fc945a370e55d369a8dc11840 golangci-lint-2.4.0-linux-amd64.tar.gz 280eb56636e9175f671cd7b755d7d67f628ae2ed00a164d1e443c43c112034e5 golangci-lint-2.10.1-linux-386.deb
70ac11f55b80ec78fd3a879249cc9255121b8dfd7f7ed4fc46ed137f4abf17e7 golangci-lint-2.4.0-linux-arm64.tar.gz 065a7d99da61dc7dfbfef2e2d7053dd3fa6672598f2747117aa4bb5f45e7df7f golangci-lint-2.10.1-linux-386.rpm
4acdc40e5cebe99e4e7ced358a05b2e71789f409b41cb4f39bbb86ccfa14b1dc golangci-lint-2.4.0-linux-armv6.tar.gz a55918c03bb413b2662287653ab2ae2fef4e37428b247dad6348724adde9d770 golangci-lint-2.10.1-linux-386.tar.gz
2a68749568fa22b4a97cb88dbea655595563c795076536aa6c087f7968784bf3 golangci-lint-2.4.0-linux-armv7.tar.gz 8aa9b3aa14f39745eeb7fc7ff50bcac683e785397d1e4bc9afd2184b12c4ce86 golangci-lint-2.10.1-linux-amd64.deb
9e3369afb023711036dcb0b4f45c9fe2792af962fa1df050c9f6ac101a6c5d73 golangci-lint-2.4.0-linux-loong64.tar.gz 62a111688e9e305032334a2cbc84f4d971b64bb3bffc99d3f80081d57fb25e32 golangci-lint-2.10.1-linux-amd64.rpm
bb9143d6329be2c4dbfffef9564078e7da7d88e7dde6c829b6263d98e072229e golangci-lint-2.4.0-linux-mips64.tar.gz dfa775874cf0561b404a02a8f4481fc69b28091da95aa697259820d429b09c99 golangci-lint-2.10.1-linux-amd64.tar.gz
5ad1765b40d56cd04d4afd805b3ba6f4bfd9b36181da93c31e9b17e483d8608d golangci-lint-2.4.0-linux-mips64le.tar.gz b3f36937e8ea1660739dc0f5c892ea59c9c21ed4e75a91a25957c561f7f79a55 golangci-lint-2.10.1-linux-arm64.deb
918936fb9c0d5ba96bef03cf4348b03938634cfcced49be1e9bb29cb5094fa73 golangci-lint-2.4.0-linux-ppc64le.tar.gz 36d50314d53683b1f1a2a6cedfb5a9468451b481c64ab9e97a8e843ea088074d golangci-lint-2.10.1-linux-arm64.rpm
f7474c638e1fb67ebbdc654b55ca0125377ea0bc88e8fee8d964a4f24eacf828 golangci-lint-2.4.0-linux-riscv64.tar.gz 6652b42ae02915eb2f9cb2a2e0cac99514c8eded8388d88ae3e06e1a52c00de8 golangci-lint-2.10.1-linux-arm64.tar.gz
b617a9543997c8bfceaffa88a75d4e595030c6add69fba800c1e4d8f5fe253dd golangci-lint-2.4.0-linux-s390x.tar.gz a32d8d318e803496812dd3461f250e52ccc7f53c47b95ce404a9cf55778ceb6a golangci-lint-2.10.1-linux-armv6.deb
7db027b03a9ba328f795215b04f594036837bc7dd0dd7cd16776b02a6167981c golangci-lint-2.4.0-netbsd-386.tar.gz 41d065f4c8ea165a1531abea644988ee2e973e4f0b49f9725ed3b979dac45112 golangci-lint-2.10.1-linux-armv6.rpm
52d8f9393f4313df0a62b752c37775e3af0b818e43e8dd28954351542d7c60bc golangci-lint-2.4.0-netbsd-amd64.tar.gz 59159a4df03aabbde69d15c7b7b3df143363cbb41f4bd4b200caffb8e34fb734 golangci-lint-2.10.1-linux-armv6.tar.gz
5c0086027fb5a4af3829e530c8115db4b35d11afe1914322eef528eb8cd38c69 golangci-lint-2.4.0-netbsd-arm64.tar.gz b2e8ec0e050a1e2251dfe1561434999d202f5a3f9fa47ce94378b0fd1662ea5a golangci-lint-2.10.1-linux-armv7.deb
6b779d6ed1aed87cefe195cc11759902b97a76551b593312c6833f2635a3488f golangci-lint-2.4.0-netbsd-armv6.tar.gz 28c9331429a497da27e9c77846063bd0e8275e878ffedb4eb9e9f21d24771cc0 golangci-lint-2.10.1-linux-armv7.rpm
f00d1f4b7ec3468a0f9fffd0d9ea036248b029b7621cbc9a59c449ef94356d09 golangci-lint-2.4.0-netbsd-armv7.tar.gz 818f33e95b273e3769284b25563b51ef6a294e9e25acf140fda5830c075a1a59 golangci-lint-2.10.1-linux-armv7.tar.gz
3ce671b0b42b58e35066493aab75a7e2826c9e079988f1ba5d814a4029faaf87 golangci-lint-2.4.0-windows-386.zip 6b6b85ed4b7c27f51097dd681523000409dde835e86e6e314e87be4bb013e2ab golangci-lint-2.10.1-linux-loong64.deb
003112f7a56746feaabf20b744054bf9acdf900c9e77176383623c4b1d76aaa9 golangci-lint-2.4.0-windows-amd64.zip 94050a0cf06169e2ae44afb307dcaafa7d7c3b38c0c23b5652cf9cb60f0c337f golangci-lint-2.10.1-linux-loong64.rpm
dc0c2092af5d47fc2cd31a1dfe7b4c7e765fab22de98bd21ef2ffcc53ad9f54f golangci-lint-2.4.0-windows-arm64.zip 25820300fccb8c961c1cdcb1f77928040c079e04c43a3a5ceb34b1cb4a1c5c8d golangci-lint-2.10.1-linux-loong64.tar.gz
0263d23e20a260cb1592d35e12a388f99efe2c51b3611fdc66fbd9db1fce664d golangci-lint-2.4.0-windows-armv6.zip 98bf39d10139fdcaa37f94950e9bbb8888660ae468847ae0bf1cb5bf67c1f68b golangci-lint-2.10.1-linux-mips64.deb
9403c03bf648e6313036e0273149d44bad1b9ad53889b6d00e4ccb842ba3c058 golangci-lint-2.4.0-windows-armv7.zip df3ce5f03808dcceaa8b683d1d06e95c885f09b59dc8e15deb840fbe2b3e3299 golangci-lint-2.10.1-linux-mips64.rpm
972508dda523067e6e6a1c8e6609d63bc7c4153819c11b947d439235cf17bac2 golangci-lint-2.10.1-linux-mips64.tar.gz
1d37f2919e183b5bf8b1777ed8c4b163d3b491d0158355a7999d647655cbbeb6 golangci-lint-2.10.1-linux-mips64le.deb
e341d031002cd09a416329ed40f674231051a38544b8f94deb2d1708ce1f4a6f golangci-lint-2.10.1-linux-mips64le.rpm
393560122b9cb5538df0c357d30eb27b6ee563533fbb9b138c8db4fd264002af golangci-lint-2.10.1-linux-mips64le.tar.gz
21ca46b6a96442e8957677a3ca059c6b93674a68a01b1c71f4e5df0ea2e96d19 golangci-lint-2.10.1-linux-ppc64le.deb
57fe0cbca0a9bbdf1547c5e8aa7d278e6896b438d72a541bae6bc62c38b43d1e golangci-lint-2.10.1-linux-ppc64le.rpm
e2883db9fa51584e5e203c64456f29993550a7faadc84e3faccdb48f0669992e golangci-lint-2.10.1-linux-ppc64le.tar.gz
aa6da0e98ab0ba3bb7582e112174c349907d5edfeff90a551dca3c6eecf92fc0 golangci-lint-2.10.1-linux-riscv64.deb
3c68d76cd884a7aad206223a980b9c20bb9ea74b560fa27ed02baf2389189234 golangci-lint-2.10.1-linux-riscv64.rpm
3bca11bfac4197205639cbd4676a5415054e629ac6c12ea10fcbe33ef852d9c3 golangci-lint-2.10.1-linux-riscv64.tar.gz
0c6aed2ce49db2586adbac72c80d871f06feb1caf4c0763a5ca98fec809a8f0b golangci-lint-2.10.1-linux-s390x.deb
16c285adfe1061d69dd8e503be69f87c7202857c6f4add74ac02e3571158fbec golangci-lint-2.10.1-linux-s390x.rpm
21011ad368eb04f024201b832095c6b5f96d0888de194cca5bfe4d9307d6364b golangci-lint-2.10.1-linux-s390x.tar.gz
7b5191e77a70485918712e31ed55159956323e4911bab1b67569c9d86e1b75eb golangci-lint-2.10.1-netbsd-386.tar.gz
07801fd38d293ebad10826f8285525a39ea91ce5ddad77d05bfa90bda9c884a9 golangci-lint-2.10.1-netbsd-amd64.tar.gz
7e7219d71c1bf33b98c328c93dc0560706dd896a1c43c44696e5222fc9d7446e golangci-lint-2.10.1-netbsd-arm64.tar.gz
92fbc90b9eec0e572269b0f5492a2895c426b086a68372fde49b7e4d4020863e golangci-lint-2.10.1-netbsd-armv6.tar.gz
f67b3ae1f47caeefa507a4ebb0c8336958a19011fe48766443212030f75d004b golangci-lint-2.10.1-netbsd-armv7.tar.gz
a40bc091c10cea84eaee1a90b84b65f5e8652113b0a600bb099e4e4d9d7caddb golangci-lint-2.10.1-windows-386.zip
c60c87695e79db8e320f0e5be885059859de52bb5ee5f11be5577828570bc2a3 golangci-lint-2.10.1-windows-amd64.zip
636ab790c8dcea8034aa34aba6031ca3893d68f7eda000460ab534341fadbab1 golangci-lint-2.10.1-windows-arm64.zip
# This is the builder on PPA that will build Go itself (inception-y), don't modify! # This is the builder on PPA that will build Go itself (inception-y), don't modify!
# #

View file

@ -73,21 +73,9 @@ var (
"./cmd/keeper", "./cmd/keeper",
} }
// Files that end up in the geth*.zip archive. // Files that end up in the geth-alltools*.zip archive (and the NSIS installer
gethArchiveFiles = []string{ // dev-tools section). Order matches the historical layout produced by ci.go.
"COPYING", allToolsBinaries = []string{"abigen", "evm", "geth", "rlpdump"}
executablePath("geth"),
}
// Files that end up in the geth-alltools*.zip archive.
allToolsArchiveFiles = []string{
"COPYING",
executablePath("abigen"),
executablePath("evm"),
executablePath("geth"),
executablePath("rlpdump"),
executablePath("clef"),
}
// Keeper build targets with their configurations // Keeper build targets with their configurations
keeperTargets = []struct { keeperTargets = []struct {
@ -107,17 +95,21 @@ var (
Tags: "ziren", Tags: "ziren",
Env: map[string]string{"GOMIPS": "softfloat", "CGO_ENABLED": "0"}, Env: map[string]string{"GOMIPS": "softfloat", "CGO_ENABLED": "0"},
}, },
{
Name: "womir",
GOOS: "wasip1",
GOARCH: "wasm",
Tags: "womir",
},
{ {
Name: "wasm-js", Name: "wasm-js",
GOOS: "js", GOOS: "js",
GOARCH: "wasm", GOARCH: "wasm",
Tags: "example",
}, },
{ {
Name: "wasm-wasi", Name: "wasm-wasi",
GOOS: "wasip1", GOOS: "wasip1",
GOARCH: "wasm", GOARCH: "wasm",
Tags: "example",
}, },
{ {
Name: "example", Name: "example",
@ -143,10 +135,6 @@ var (
BinaryName: "rlpdump", BinaryName: "rlpdump",
Description: "Developer utility tool that prints RLP structures.", Description: "Developer utility tool that prints RLP structures.",
}, },
{
BinaryName: "clef",
Description: "Ethereum account management tool.",
},
} }
// A debian package is created for all executables listed here. // A debian package is created for all executables listed here.
@ -168,8 +156,6 @@ var (
"focal", // 20.04, EOL: 04/2030 "focal", // 20.04, EOL: 04/2030
"jammy", // 22.04, EOL: 04/2032 "jammy", // 22.04, EOL: 04/2032
"noble", // 24.04, EOL: 04/2034 "noble", // 24.04, EOL: 04/2034
"oracular", // 24.10, EOL: 07/2025
"plucky", // 25.04, EOL: 01/2026
} }
// This is where the tests should be unpacked. // This is where the tests should be unpacked.
@ -178,13 +164,35 @@ var (
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
func executablePath(name string) string { // executablePath returns the path to a built binary in GOBIN, applying the
if runtime.GOOS == "windows" { // platform-specific extension for the given target OS.
func executablePath(name, targetOS string) string {
if targetOS == "windows" {
name += ".exe" name += ".exe"
} }
return filepath.Join(GOBIN, name) return filepath.Join(GOBIN, name)
} }
// gethArchiveFiles returns the file list for the geth-{platform}-{ver}.zip
// archive, with binary paths resolved for the target OS.
func gethArchiveFiles(targetOS string) []string {
return []string{
"COPYING",
executablePath("geth", targetOS),
}
}
// allToolsArchiveFiles returns the file list for the
// geth-alltools-{platform}-{ver}.zip archive, with binary paths resolved for
// the target OS.
func allToolsArchiveFiles(targetOS string) []string {
files := []string{"COPYING"}
for _, name := range allToolsBinaries {
files = append(files, executablePath(name, targetOS))
}
return files
}
func main() { func main() {
log.SetFlags(log.Lshortfile) log.SetFlags(log.Lshortfile)
@ -231,6 +239,7 @@ func main() {
func doInstall(cmdline []string) { func doInstall(cmdline []string) {
var ( var (
dlgo = flag.Bool("dlgo", false, "Download Go and build with it") dlgo = flag.Bool("dlgo", false, "Download Go and build with it")
targetOS = flag.String("os", runtime.GOOS, "Target OS to cross build for")
arch = flag.String("arch", "", "Architecture to cross build for") arch = flag.String("arch", "", "Architecture to cross build for")
cc = flag.String("cc", "", "C compiler to cross build with") cc = flag.String("cc", "", "C compiler to cross build with")
staticlink = flag.Bool("static", false, "Create statically-linked executable") staticlink = flag.Bool("static", false, "Create statically-linked executable")
@ -239,7 +248,7 @@ func doInstall(cmdline []string) {
env := build.Env() env := build.Env()
// Configure the toolchain. // Configure the toolchain.
tc := build.GoToolchain{GOARCH: *arch, CC: *cc} tc := build.GoToolchain{GOOS: *targetOS, GOARCH: *arch, CC: *cc}
if *dlgo { if *dlgo {
csdb := download.MustLoadChecksums("build/checksums.txt") csdb := download.MustLoadChecksums("build/checksums.txt")
tc.Root = build.DownloadGo(csdb) tc.Root = build.DownloadGo(csdb)
@ -253,7 +262,7 @@ func doInstall(cmdline []string) {
} }
// Configure the build. // Configure the build.
gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...) gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags, *targetOS)...)
// Show packages during build. // Show packages during build.
gobuild.Args = append(gobuild.Args, "-v") gobuild.Args = append(gobuild.Args, "-v")
@ -268,7 +277,7 @@ func doInstall(cmdline []string) {
// Do the build! // Do the build!
for _, pkg := range packages { for _, pkg := range packages {
args := slices.Clone(gobuild.Args) args := slices.Clone(gobuild.Args)
args = append(args, "-o", executablePath(path.Base(pkg))) args = append(args, "-o", executablePath(path.Base(pkg), *targetOS))
args = append(args, pkg) args = append(args, pkg)
build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env}) build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env})
} }
@ -295,7 +304,13 @@ func doInstallKeeper(cmdline []string) {
tc.GOARCH = target.GOARCH tc.GOARCH = target.GOARCH
tc.GOOS = target.GOOS tc.GOOS = target.GOOS
tc.CC = target.CC tc.CC = target.CC
gobuild := tc.Go("build", buildFlags(env, true, []string{target.Tags})...) // An empty GOOS means "build for the host OS"; thread that through to
// buildFlags so platform-specific linker flags are picked correctly.
targetOS := target.GOOS
if targetOS == "" {
targetOS = runtime.GOOS
}
gobuild := tc.Go("build", buildFlags(env, true, []string{target.Tags}, targetOS)...)
gobuild.Dir = "./cmd/keeper" gobuild.Dir = "./cmd/keeper"
gobuild.Args = append(gobuild.Args, "-v") gobuild.Args = append(gobuild.Args, "-v")
@ -305,14 +320,15 @@ func doInstallKeeper(cmdline []string) {
outputName := fmt.Sprintf("keeper-%s", target.Name) outputName := fmt.Sprintf("keeper-%s", target.Name)
args := slices.Clone(gobuild.Args) args := slices.Clone(gobuild.Args)
args = append(args, "-o", executablePath(outputName)) args = append(args, "-o", executablePath(outputName, targetOS))
args = append(args, ".") args = append(args, ".")
build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env}) build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env, Dir: gobuild.Dir})
} }
} }
// buildFlags returns the go tool flags for building. // buildFlags returns the go tool flags for building. targetOS is the OS we
func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (flags []string) { // are producing binaries for.
func buildFlags(env build.Environment, staticLinking bool, buildTags []string, targetOS string) (flags []string) {
var ld []string var ld []string
// See https://github.com/golang/go/issues/33772#issuecomment-528176001 // See https://github.com/golang/go/issues/33772#issuecomment-528176001
// We need to set --buildid to the linker here, and also pass --build-id to the // We need to set --buildid to the linker here, and also pass --build-id to the
@ -324,10 +340,10 @@ func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (
} }
// Strip DWARF on darwin. This used to be required for certain things, // Strip DWARF on darwin. This used to be required for certain things,
// and there is no downside to this, so we just keep doing it. // and there is no downside to this, so we just keep doing it.
if runtime.GOOS == "darwin" { if targetOS == "darwin" {
ld = append(ld, "-s") ld = append(ld, "-s")
} }
if runtime.GOOS == "linux" { if targetOS == "linux" {
// Enforce the stacksize to 8M, which is the case on most platforms apart from // Enforce the stacksize to 8M, which is the case on most platforms apart from
// alpine Linux. // alpine Linux.
// See https://sourceware.org/binutils/docs-2.23.1/ld/Options.html#Options // See https://sourceware.org/binutils/docs-2.23.1/ld/Options.html#Options
@ -436,7 +452,7 @@ func doTest(cmdline []string) {
// downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures. // downloadSpecTestFixtures downloads and extracts the execution-spec-tests fixtures.
func downloadSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string { func downloadSpecTestFixtures(csdb *download.ChecksumDB, cachedir string) string {
ext := ".tar.gz" ext := ".tar.gz"
base := "fixtures_develop" base := "fixtures"
archivePath := filepath.Join(cachedir, base+ext) archivePath := filepath.Join(cachedir, base+ext)
if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil { if err := csdb.DownloadFileFromKnownURL(archivePath); err != nil {
log.Fatal(err) log.Fatal(err)
@ -680,6 +696,7 @@ func downloadProtoc(cachedir string) string {
// Release Packaging // Release Packaging
func doArchive(cmdline []string) { func doArchive(cmdline []string) {
var ( var (
targetOS = flag.String("os", runtime.GOOS, "Target OS the binaries were built for")
arch = flag.String("arch", runtime.GOARCH, "Architecture cross packaging") arch = flag.String("arch", runtime.GOARCH, "Architecture cross packaging")
atype = flag.String("type", "zip", "Type of archive to write (zip|tar)") atype = flag.String("type", "zip", "Type of archive to write (zip|tar)")
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`) signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`)
@ -699,15 +716,15 @@ func doArchive(cmdline []string) {
var ( var (
env = build.Env() env = build.Env()
basegeth = archiveBasename(*arch, version.Archive(env.Commit)) basegeth = archiveBasename(*targetOS, *arch, version.Archive(env.Commit))
geth = "geth-" + basegeth + ext geth = "geth-" + basegeth + ext
alltools = "geth-alltools-" + basegeth + ext alltools = "geth-alltools-" + basegeth + ext
) )
maybeSkipArchive(env) maybeSkipArchive(env)
if err := build.WriteArchive(geth, gethArchiveFiles); err != nil { if err := build.WriteArchive(geth, gethArchiveFiles(*targetOS)); err != nil {
log.Fatal(err) log.Fatal(err)
} }
if err := build.WriteArchive(alltools, allToolsArchiveFiles); err != nil { if err := build.WriteArchive(alltools, allToolsArchiveFiles(*targetOS)); err != nil {
log.Fatal(err) log.Fatal(err)
} }
for _, archive := range []string{geth, alltools} { for _, archive := range []string{geth, alltools} {
@ -733,7 +750,11 @@ func doKeeperArchive(cmdline []string) {
maybeSkipArchive(env) maybeSkipArchive(env)
files := []string{"COPYING"} files := []string{"COPYING"}
for _, target := range keeperTargets { for _, target := range keeperTargets {
files = append(files, executablePath(fmt.Sprintf("keeper-%s", target.Name))) targetOS := target.GOOS
if targetOS == "" {
targetOS = runtime.GOOS
}
files = append(files, executablePath(fmt.Sprintf("keeper-%s", target.Name), targetOS))
} }
if err := build.WriteArchive(keeper, files); err != nil { if err := build.WriteArchive(keeper, files); err != nil {
log.Fatal(err) log.Fatal(err)
@ -743,8 +764,8 @@ func doKeeperArchive(cmdline []string) {
} }
} }
func archiveBasename(arch string, archiveVersion string) string { func archiveBasename(targetOS, arch, archiveVersion string) string {
platform := runtime.GOOS + "-" + arch platform := targetOS + "-" + arch
if arch == "arm" { if arch == "arm" {
platform += os.Getenv("GOARM") platform += os.Getenv("GOARM")
} }
@ -1198,7 +1219,7 @@ func doWindowsInstaller(cmdline []string) {
var ( var (
arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging") arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging")
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`) signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`)
signify = flag.String("signify key", "", `Environment variable holding the signify signing key (e.g. WINDOWS_SIGNIFY_KEY)`) signify = flag.String("signify", "", `Environment variable holding the signify signing key (e.g. WINDOWS_SIGNIFY_KEY)`)
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`) upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`) workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
) )
@ -1207,13 +1228,13 @@ func doWindowsInstaller(cmdline []string) {
env := build.Env() env := build.Env()
maybeSkipArchive(env) maybeSkipArchive(env)
// Aggregate binaries that are included in the installer // Aggregate binaries that are included in the installer.
var ( var (
devTools []string devTools []string
allTools []string allTools []string
gethTool string gethTool string
) )
for _, file := range allToolsArchiveFiles { for _, file := range allToolsArchiveFiles("windows") {
if file == "COPYING" { // license, copied later if file == "COPYING" { // license, copied later
continue continue
} }
@ -1250,16 +1271,24 @@ func doWindowsInstaller(cmdline []string) {
if env.Commit != "" { if env.Commit != "" {
ver[2] += "-" + env.Commit[:8] ver[2] += "-" + env.Commit[:8]
} }
installer, err := filepath.Abs("geth-" + archiveBasename(*arch, version.Archive(env.Commit)) + ".exe") installer, err := filepath.Abs("geth-" + archiveBasename("windows", *arch, version.Archive(env.Commit)) + ".exe")
if err != nil { if err != nil {
log.Fatalf("Failed to convert installer file path: %v", err) log.Fatalf("Failed to convert installer file path: %v", err)
} }
build.MustRunCommand("makensis.exe", // makensis on Windows is "makensis.exe" with /D-style defines; on Linux
"/DOUTPUTFILE="+installer, // (and other Unixes) the binary is "makensis" and accepts -D.
"/DMAJORVERSION="+ver[0], makensisCmd := "makensis"
"/DMINORVERSION="+ver[1], defineFlag := "-D"
"/DBUILDVERSION="+ver[2], if runtime.GOOS == "windows" {
"/DARCH="+*arch, makensisCmd = "makensis.exe"
defineFlag = "/D"
}
build.MustRunCommand(makensisCmd,
defineFlag+"OUTPUTFILE="+installer,
defineFlag+"MAJORVERSION="+ver[0],
defineFlag+"MINORVERSION="+ver[1],
defineFlag+"BUILDVERSION="+ver[2],
defineFlag+"ARCH="+*arch,
filepath.Join(*workdir, "geth.nsi"), filepath.Join(*workdir, "geth.nsi"),
) )
// Sign and publish installer. // Sign and publish installer.

View file

@ -215,7 +215,7 @@ func generate(c *cli.Context) error {
code string code string
err error err error
) )
if c.IsSet(v2Flag.Name) { if c.Bool(v2Flag.Name) {
code, err = abigen.BindV2(types, abis, bins, c.String(pkgFlag.Name), libs, aliases) code, err = abigen.BindV2(types, abis, bins, c.String(pkgFlag.Name), libs, aliases)
} else { } else {
code, err = abigen.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), libs, aliases) code, err = abigen.Bind(types, abis, bins, sigs, c.String(pkgFlag.Name), libs, aliases)

View file

@ -1,922 +0,0 @@
# Clef
Clef can be used to sign transactions and data and is meant as a(n eventual) replacement for Geth's account management. This allows DApps to not depend on Geth's account management. When a DApp wants to sign data (or a transaction), it can send the content to Clef, which will then provide the user with context and ask for permission to sign the content. If the user grants the signing request, Clef will send the signature back to the DApp.
This setup allows a DApp to connect to a remote Ethereum node and send transactions that are locally signed. This can help in situations when a DApp is connected to an untrusted remote Ethereum node, because a local one is not available, not synchronized with the chain, or is a node that has no built-in (or limited) account management.
Clef can run as a daemon on the same machine, off a usb-stick like [USB armory](https://inversepath.com/usbarmory), or even a separate VM in a [QubesOS](https://www.qubes-os.org/) type setup.
Check out the
* [CLI tutorial](tutorial.md) for some concrete examples on how Clef works.
* [Setup docs](docs/setup.md) for information on how to configure Clef on QubesOS or USB Armory.
* [Data types](datatypes.md) for details on the communication messages between Clef and an external UI.
## Command line flags
Clef accepts the following command line options:
```
COMMANDS:
init Initialize the signer, generate secret storage
attest Attest that a js-file is to be used
setpw Store a credential for a keystore file
delpw Remove a credential for a keystore file
gendoc Generate documentation about json-rpc format
help Shows a list of commands or help for one command
GLOBAL OPTIONS:
--loglevel value log level to emit to the screen (default: 4)
--keystore value Directory for the keystore (default: "$HOME/.ethereum/keystore")
--configdir value Directory for Clef configuration (default: "$HOME/.clef")
--chainid value Chain id to use for signing (1=mainnet, 17000=Holesky) (default: 1)
--lightkdf Reduce key-derivation RAM & CPU usage at some expense of KDF strength
--nousb Disables monitoring for and managing USB hardware wallets
--pcscdpath value Path to the smartcard daemon (pcscd) socket file (default: "/run/pcscd/pcscd.comm")
--http.addr value HTTP-RPC server listening interface (default: "localhost")
--http.vhosts value Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard. (default: "localhost")
--ipcdisable Disable the IPC-RPC server
--ipcpath Filename for IPC socket/pipe within the datadir (explicit paths escape it)
--http Enable the HTTP-RPC server
--http.port value HTTP-RPC server listening port (default: 8550)
--signersecret value A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash
--4bytedb-custom value File used for writing new 4byte-identifiers submitted via API (default: "./4byte-custom.json")
--auditlog value File used to emit audit logs. Set to "" to disable (default: "audit.log")
--rules value Path to the rule file to auto-authorize requests with
--stdio-ui Use STDIN/STDOUT as a channel for an external UI. This means that an STDIN/STDOUT is used for RPC-communication with a e.g. a graphical user interface, and can be used when Clef is started by an external process.
--stdio-ui-test Mechanism to test interface between Clef and UI. Requires 'stdio-ui'.
--advanced If enabled, issues warnings instead of rejections for suspicious requests. Default off
--suppress-bootwarn If set, does not show the warning during boot
--help, -h show help
--version, -v print the version
```
Example:
```
$ clef -keystore /my/keystore -chainid 4
```
## Security model
The security model of Clef is as follows:
* One critical component (the Clef binary / daemon) is responsible for handling cryptographic operations: signing, private keys, encryption/decryption of keystore files.
* Clef has a well-defined 'external' API.
* The 'external' API is considered UNTRUSTED.
* Clef also communicates with whatever process that invoked the binary, via stdin/stdout.
* This channel is considered 'trusted'. Over this channel, approvals and passwords are communicated.
The general flow for signing a transaction using e.g. Geth is as follows:
![image](sign_flow.png)
In this case, `geth` would be started with `--signer http://localhost:8550` and would relay requests to `eth.sendTransaction`.
## TODOs
Some snags and todos
* [ ] Clef should take a startup param "--no-change", for UIs that do not contain the capability to perform changes to things, only approve/deny. Such a UI should be able to start the signer in a more secure mode by telling it that it only wants approve/deny capabilities.
* [x] It would be nice if Clef could collect new 4byte-id:s/method selectors, and have a secondary database for those (`4byte_custom.json`). Users could then (optionally) submit their collections for inclusion upstream.
* [ ] It should be possible to configure Clef to check if an account is indeed known to it, before passing on to the UI. The reason it currently does not, is that it would make it possible to enumerate accounts if it immediately returned "unknown account" (side channel attack).
* [x] It should be possible to configure Clef to auto-allow listing (certain) accounts, instead of asking every time.
* [x] Done Upon startup, Clef should spit out some info to the caller (particularly important when executed in `stdio-ui`-mode), invoking methods with the following info:
* [x] Version info about the signer
* [x] Address of API (HTTP/IPC)
* [ ] List of known accounts
* [ ] Have a default timeout on signing operations, so that if the user has not answered within e.g. 60 seconds, the request is rejected.
* [ ] `account_signRawTransaction`
* [ ] `account_bulkSignTransactions([] transactions)` should
* only exist if enabled via config/flag
* only allow non-data-sending transactions
* all txs must use the same `from`-account
* let the user confirm, showing
* the total amount
* the number of unique recipients
* Geth todos
- The signer should pass the `Origin` header as call-info to the UI. As of right now, the way that info about the request is put together is a bit of a hack into the HTTP server. This could probably be greatly improved.
- Relay: Geth should be started in `geth --signer localhost:8550`.
- Currently, the Geth APIs use `common.Address` in the arguments to transaction submission (e.g `to` field). This type is 20 `bytes`, and is incapable of carrying checksum information. The signer uses `common.MixedcaseAddress`, which retains the original input.
- The Geth API should switch to use the same type, and relay `to`-account verbatim to the external API.
* [x] Storage
* [x] An encrypted key-value storage should be implemented.
* See [rules.md](rules.md) for more info about this.
* Another potential thing to introduce is pairing.
* To prevent spurious requests which users just accept, implement a way to "pair" the caller with the signer (external API).
* Thus Geth/cpp would cryptographically handshake and afterwards the caller would be allowed to make signing requests.
* This feature would make the addition of rules less dangerous.
* Wallets / accounts. Add API methods for wallets.
## Communication
### External API
Clef listens to HTTP requests on `http.addr`:`http.port` (or to IPC on `ipcpath`), with the same JSON-RPC standard as Geth. The messages are expected to be [JSON-RPC 2.0 standard](https://www.jsonrpc.org/specification).
Some of these calls can require user interaction. Clients must be aware that responses may be delayed significantly or may never be received if a user decides to ignore the confirmation request.
The External API is **untrusted**: it does not accept credentials, nor does it expect that requests have any authority.
### Internal UI API
Clef has one native console-based UI, for operation without any standalone tools. However, there is also an API to communicate with an external UI. To enable that UI, the signer needs to be executed with the `--stdio-ui` option, which allocates `stdin` / `stdout` for the UI API.
An example (insecure) proof-of-concept has been implemented in `pythonsigner.py`.
The model is as follows:
* The user starts the UI app (`pythonsigner.py`).
* The UI app starts `clef` with `--stdio-ui`, and listens to the
process output for confirmation-requests.
* `clef` opens the external HTTP API.
* When the `signer` receives requests, it sends a JSON-RPC request via `stdout`.
* The UI app prompts the user accordingly, and responds to `clef`.
* `clef` signs (or not), and responds to the original request.
## External API
See the [external API changelog](extapi_changelog.md) for information about changes to this API.
### Encoding
- number: positive integers that are hex encoded
- data: hex encoded data
- string: ASCII string
All hex encoded values must be prefixed with `0x`.
### account_new
#### Create new password protected account
The signer will generate a new private key, encrypt it according to [web3 keystore spec](https://ethereum.org/en/developers/docs/data-structures-and-encoding/web3-secret-storage/) and store it in the keystore directory.
The client is responsible for creating a backup of the keystore. If the keystore is lost there is no method of retrieving lost accounts.
#### Arguments
None
#### Result
- address [string]: account address that is derived from the generated key
#### Sample call
```json
{
"id": 0,
"jsonrpc": "2.0",
"method": "account_new",
"params": []
}
```
Response
```json
{
"id": 0,
"jsonrpc": "2.0",
"result": "0xbea9183f8f4f03d427f6bcea17388bdff1cab133"
}
```
### account_list
#### List available accounts
List all accounts that this signer currently manages
#### Arguments
None
#### Result
- array with account records:
- account.address [string]: account address that is derived from the generated key
#### Sample call
```json
{
"id": 1,
"jsonrpc": "2.0",
"method": "account_list"
}
```
Response
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": [
"0xafb2f771f58513609765698f65d3f2f0224a956f",
"0xbea9183f8f4f03d427f6bcea17388bdff1cab133"
]
}
```
### account_signTransaction
#### Sign transactions
Signs a transaction and responds with the signed transaction in RLP-encoded and JSON forms.
#### Arguments
1. transaction object:
- `from` [address]: account to send the transaction from
- `to` [address]: receiver account. If omitted or `0x`, will cause contract creation.
- `gas` [number]: maximum amount of gas to burn
- `gasPrice` [number]: gas price
- `value` [number:optional]: amount of Wei to send with the transaction
- `data` [data:optional]: input data
- `nonce` [number]: account nonce
2. method signature [string:optional]
- The method signature, if present, is to aid decoding the calldata. Should consist of `methodname(paramtype,...)`, e.g. `transfer(uint256,address)`. The signer may use this data to parse the supplied calldata, and show the user. The data, however, is considered totally untrusted, and reliability is not expected.
#### Result
- raw [data]: signed transaction in RLP encoded form
- tx [json]: signed transaction in JSON form
#### Sample call
```json
{
"id": 2,
"jsonrpc": "2.0",
"method": "account_signTransaction",
"params": [
{
"from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
"gas": "0x55555",
"gasPrice": "0x1234",
"input": "0xabcd",
"nonce": "0x0",
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"value": "0x1234"
}
]
}
```
Response
```json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
"tx": {
"nonce": "0x0",
"gasPrice": "0x1234",
"gas": "0x55555",
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"value": "0x1234",
"input": "0xabcd",
"v": "0x26",
"r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e",
"s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
"hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"
}
}
}
```
#### Sample call with ABI-data
```json
{
"id": 67,
"jsonrpc": "2.0",
"method": "account_signTransaction",
"params": [
{
"from": "0x694267f14675d7e1b9494fd8d72fefe1755710fa",
"gas": "0x333",
"gasPrice": "0x1",
"nonce": "0x0",
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"value": "0x0",
"data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"
},
"safeSend(address)"
]
}
```
Response
```json
{
"jsonrpc": "2.0",
"id": 67,
"result": {
"raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
"tx": {
"nonce": "0x0",
"gasPrice": "0x1",
"gas": "0x333",
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"value": "0x0",
"input": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012",
"v": "0x26",
"r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e",
"s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
"hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"
}
}
}
```
Bash example:
```bash
> curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/
{"jsonrpc":"2.0","id":67,"result":{"raw":"0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","tx":{"nonce":"0x0","gasPrice":"0x1","gas":"0x333","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0","value":"0x0","input":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012","v":"0x26","r":"0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e","s":"0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","hash":"0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"}}}
```
### account_signData
#### Sign data
Signs a chunk of data and returns the calculated signature.
#### Arguments
- content type [string]: type of signed data
- `text/validator`: hex data with a custom validator defined in a contract
- `application/clique`: [clique](https://github.com/ethereum/EIPs/issues/225) headers
- `text/plain`: simple hex data validated by `account_ecRecover`
- account [address]: account to sign with
- data [object]: data to sign
#### Result
- calculated signature [data]
#### Sample call
```json
{
"id": 3,
"jsonrpc": "2.0",
"method": "account_signData",
"params": [
"data/plain",
"0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db",
"0xaabbccdd"
]
}
```
Response
```json
{
"id": 3,
"jsonrpc": "2.0",
"result": "0x5b6693f153b48ec1c706ba4169960386dbaa6903e249cc79a8e6ddc434451d417e1e57327872c7f538beeb323c300afa9999a3d4a5de6caf3be0d5ef832b67ef1c"
}
```
### account_signTypedData
#### Sign data
Signs a chunk of structured data conformant to [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) and returns the calculated signature.
#### Arguments
- account [address]: account to sign with
- data [object]: data to sign
#### Result
- calculated signature [data]
#### Sample call
```json
{
"id": 68,
"jsonrpc": "2.0",
"method": "account_signTypedData",
"params": [
"0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826",
{
"types": {
"EIP712Domain": [
{
"name": "name",
"type": "string"
},
{
"name": "version",
"type": "string"
},
{
"name": "chainId",
"type": "uint256"
},
{
"name": "verifyingContract",
"type": "address"
}
],
"Person": [
{
"name": "name",
"type": "string"
},
{
"name": "wallet",
"type": "address"
}
],
"Mail": [
{
"name": "from",
"type": "Person"
},
{
"name": "to",
"type": "Person"
},
{
"name": "contents",
"type": "string"
}
]
},
"primaryType": "Mail",
"domain": {
"name": "Ether Mail",
"version": "1",
"chainId": 1,
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
},
"message": {
"from": {
"name": "Cow",
"wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
},
"to": {
"name": "Bob",
"wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
},
"contents": "Hello, Bob!"
}
}
]
}
```
Response
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": "0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c"
}
```
### account_ecRecover
#### Recover the signing address
Derive the address from the account that was used to sign data with content type `text/plain` and the signature.
#### Arguments
- data [data]: data that was signed
- signature [data]: the signature to verify
#### Result
- derived account [address]
#### Sample call
```json
{
"id": 4,
"jsonrpc": "2.0",
"method": "account_ecRecover",
"params": [
"0xaabbccdd",
"0x5b6693f153b48ec1c706ba4169960386dbaa6903e249cc79a8e6ddc434451d417e1e57327872c7f538beeb323c300afa9999a3d4a5de6caf3be0d5ef832b67ef1c"
]
}
```
Response
```json
{
"id": 4,
"jsonrpc": "2.0",
"result": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db"
}
```
### account_version
#### Get external API version
Get the version of the external API used by Clef.
#### Arguments
None
#### Result
* external API version [string]
#### Sample call
```json
{
"id": 0,
"jsonrpc": "2.0",
"method": "account_version",
"params": []
}
```
Response
```json
{
"id": 0,
"jsonrpc": "2.0",
"result": "6.0.0"
}
```
## UI API
These methods needs to be implemented by a UI listener.
By starting the signer with the switch `--stdio-ui-test`, the signer will invoke all known methods, and expect the UI to respond with
denials. This can be used during development to ensure that the API is (at least somewhat) correctly implemented.
See `pythonsigner`, which can be invoked via `python3 pythonsigner.py test` to perform the 'denial-handshake-test'.
All methods in this API use object-based parameters, so that there can be no mixup of parameters: each piece of data is accessed by key.
See the [ui API changelog](intapi_changelog.md) for information about changes to this API.
OBS! A slight deviation from `json` standard is in place: every request and response should be confined to a single line.
Whereas the `json` specification allows for linebreaks, linebreaks __should not__ be used in this communication channel, to make
things simpler for both parties.
### ApproveTx / `ui_approveTx`
Invoked when there's a transaction for approval.
#### Sample call
Here's a method invocation:
```bash
curl -i -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/
```
Results in the following invocation on the UI:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "ui_approveTx",
"params": [
{
"transaction": {
"from": "0x0x694267f14675d7e1b9494fd8d72fefe1755710fa",
"to": "0x0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"gas": "0x333",
"gasPrice": "0x1",
"value": "0x0",
"nonce": "0x0",
"data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012",
"input": null
},
"call_info": [
{
"type": "WARNING",
"message": "Invalid checksum on to-address"
},
{
"type": "Info",
"message": "safeSend(address: 0x0000000000000000000000000000000000000012)"
}
],
"meta": {
"remote": "127.0.0.1:48486",
"local": "localhost:8550",
"scheme": "HTTP/1.1"
}
}
]
}
```
The same method invocation, but with invalid data:
```bash
curl -i -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000002000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "ui_approveTx",
"params": [
{
"transaction": {
"from": "0x0x694267f14675d7e1b9494fd8d72fefe1755710fa",
"to": "0x0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"gas": "0x333",
"gasPrice": "0x1",
"value": "0x0",
"nonce": "0x0",
"data": "0x4401a6e40000000000000002000000000000000000000000000000000000000000000012",
"input": null
},
"call_info": [
{
"type": "WARNING",
"message": "Invalid checksum on to-address"
},
{
"type": "WARNING",
"message": "Transaction data did not match ABI-interface: WARNING: Supplied data is stuffed with extra data. \nWant 0000000000000002000000000000000000000000000000000000000000000012\nHave 0000000000000000000000000000000000000000000000000000000000000012\nfor method safeSend(address)"
}
],
"meta": {
"remote": "127.0.0.1:48492",
"local": "localhost:8550",
"scheme": "HTTP/1.1"
}
}
]
}
```
One which has missing `to`, but with no `data`:
```json
{
"jsonrpc": "2.0",
"id": 3,
"method": "ui_approveTx",
"params": [
{
"transaction": {
"from": "",
"to": null,
"gas": "0x0",
"gasPrice": "0x0",
"value": "0x0",
"nonce": "0x0",
"data": null,
"input": null
},
"call_info": [
{
"type": "CRITICAL",
"message": "Tx will create contract with empty code!"
}
],
"meta": {
"remote": "signer binary",
"local": "main",
"scheme": "in-proc"
}
}
]
}
```
### ApproveListing / `ui_approveListing`
Invoked when a request for account listing has been made.
#### Sample call
```json
{
"jsonrpc": "2.0",
"id": 5,
"method": "ui_approveListing",
"params": [
{
"accounts": [
{
"url": "keystore:///home/bazonk/.ethereum/keystore/UTC--2017-11-20T14-44-54.089682944Z--123409812340981234098123409812deadbeef42",
"address": "0x123409812340981234098123409812deadbeef42"
},
{
"url": "keystore:///home/bazonk/.ethereum/keystore/UTC--2017-11-23T21-59-03.199240693Z--cafebabedeadbeef34098123409812deadbeef42",
"address": "0xcafebabedeadbeef34098123409812deadbeef42"
}
],
"meta": {
"remote": "signer binary",
"local": "main",
"scheme": "in-proc"
}
}
]
}
```
### ApproveSignData / `ui_approveSignData`
#### Sample call
```json
{
"jsonrpc": "2.0",
"id": 4,
"method": "ui_approveSignData",
"params": [
{
"address": "0x123409812340981234098123409812deadbeef42",
"raw_data": "0x01020304",
"messages": [
{
"name": "message",
"value": "\u0019Ethereum Signed Message:\n4\u0001\u0002\u0003\u0004",
"type": "text/plain"
}
],
"hash": "0x7e3a4e7a9d1744bc5c675c25e1234ca8ed9162bd17f78b9085e48047c15ac310",
"meta": {
"remote": "signer binary",
"local": "main",
"scheme": "in-proc"
}
}
]
}
```
### ApproveNewAccount / `ui_approveNewAccount`
Invoked when a request for creating a new account has been made.
#### Sample call
```json
{
"jsonrpc": "2.0",
"id": 4,
"method": "ui_approveNewAccount",
"params": [
{
"meta": {
"remote": "signer binary",
"local": "main",
"scheme": "in-proc"
}
}
]
}
```
### ShowInfo / `ui_showInfo`
The UI should show the info (a single message) to the user. Does not expect response.
#### Sample call
```json
{
"jsonrpc": "2.0",
"id": 9,
"method": "ui_showInfo",
"params": [
"Tests completed"
]
}
```
### ShowError / `ui_showError`
The UI should show the error (a single message) to the user. Does not expect response.
```json
{
"jsonrpc": "2.0",
"id": 2,
"method": "ui_showError",
"params": [
"Something bad happened!"
]
}
```
### OnApprovedTx / `ui_onApprovedTx`
`OnApprovedTx` is called when a transaction has been approved and signed. The call contains the return value that will be sent to the external caller. The return value from this method is ignored - the reason for having this callback is to allow the ruleset to keep track of approved transactions.
When implementing rate-limited rules, this callback should be used.
TLDR; Use this method to keep track of signed transactions, instead of using the data in `ApproveTx`.
Example call:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "ui_onApprovedTx",
"params": [
{
"raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
"tx": {
"nonce": "0x0",
"gasPrice": "0x1",
"gas": "0x333",
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"value": "0x0",
"input": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012",
"v": "0x26",
"r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e",
"s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663",
"hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"
}
}
]
}
```
### OnSignerStartup / `ui_onSignerStartup`
This method provides the UI with information about what API version the signer uses (both internal and external) as well as build-info and external API,
in k/v-form.
Example call:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "ui_onSignerStartup",
"params": [
{
"info": {
"extapi_http": "http://localhost:8550",
"extapi_ipc": null,
"extapi_version": "2.0.0",
"intapi_version": "1.2.0"
}
}
]
}
```
### OnInputRequired / `ui_onInputRequired`
Invoked when Clef requires user input (e.g. a password).
Example call:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "ui_onInputRequired",
"params": [
{
"title": "Account password",
"prompt": "Please enter the password for account 0x694267f14675d7e1b9494fd8d72fefe1755710fa",
"isPassword": true
}
]
}
```
### Rules for UI apis
A UI should conform to the following rules.
* A UI MUST NOT load any external resources that were not embedded/part of the UI package.
* For example, not load icons, stylesheets from the internet
* Not load files from the filesystem, unless they reside in the same local directory (e.g. config files)
* A Graphical UI MUST show the blocky-identicon for ethereum addresses.
* A UI MUST warn display appropriate warning if the destination-account is formatted with invalid checksum.
* A UI MUST NOT open any ports or services
* The signer opens the public port
* A UI SHOULD verify the permissions on the signer binary, and refuse to execute or warn if permissions allow non-user write.
* A UI SHOULD inform the user about the `SHA256` or `MD5` hash of the binary being executed
* A UI SHOULD NOT maintain a secondary storage of data, e.g. list of accounts
* The signer provides accounts
* A UI SHOULD, to the best extent possible, use static linking / bundling, so that required libraries are bundled
along with the UI.
### UI Implementations
There are a couple of implementation for a UI. We'll try to keep this list up to date.
| Name | Repo | UI type| No external resources| Blocky support| Verifies permissions | Hash information | No secondary storage | Statically linked| Can modify parameters|
| ---- | ---- | -------| ---- | ---- | ---- |---- | ---- | ---- | ---- |
| QtSigner| https://github.com/holiman/qtsigner/ | Python3/QT-based| :+1:| :+1:| :+1:| :+1:| :+1:| :x: | :+1: (partially)|
| GtkSigner| https://github.com/holiman/gtksigner | Python3/GTK-based| :+1:| :x:| :x:| :+1:| :+1:| :x: | :x: |
| Frame | https://github.com/floating/frame/commits/go-signer | Electron-based| :x:| :x:| :x:| :x:| ?| :x: | :x: |
| Clef UI| https://github.com/ethereum/clef-ui | Golang/QT-based| :+1:| :+1:| :x:| :+1:| :+1:| :x: | :+1: (approve tx only)|

View file

@ -1,121 +0,0 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"
)
// TestImportRaw tests clef --importraw
func TestImportRaw(t *testing.T) {
t.Parallel()
keyPath := filepath.Join(t.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
t.Run("happy-path", func(t *testing.T) {
t.Parallel()
// Run clef importraw
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword").input("myverylongpassword")
if out := string(clef.Output()); !strings.Contains(out,
"Key imported:\n Address 0x9160DC9105f7De5dC5E7f3d97ef11DA47269BdA6") {
t.Logf("Output\n%v", out)
t.Error("Failure")
}
})
// tests clef --importraw with mismatched passwords.
t.Run("pw-mismatch", func(t *testing.T) {
t.Parallel()
// Run clef importraw
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword1").input("myverylongpassword2").WaitExit()
if have, want := clef.StderrText(), "Passwords do not match\n"; have != want {
t.Errorf("have %q, want %q", have, want)
}
})
// tests clef --importraw with a too short password.
t.Run("short-pw", func(t *testing.T) {
t.Parallel()
// Run clef importraw
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("shorty").input("shorty").WaitExit()
if have, want := clef.StderrText(),
"password requirements not met: password too short (<10 characters)\n"; have != want {
t.Errorf("have %q, want %q", have, want)
}
})
}
// TestListAccounts tests clef --list-accounts
func TestListAccounts(t *testing.T) {
t.Parallel()
keyPath := filepath.Join(t.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
t.Run("no-accounts", func(t *testing.T) {
t.Parallel()
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "list-accounts")
if out := string(clef.Output()); !strings.Contains(out, "The keystore is empty.") {
t.Logf("Output\n%v", out)
t.Error("Failure")
}
})
t.Run("one-account", func(t *testing.T) {
t.Parallel()
// First, we need to import
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword").input("myverylongpassword").WaitExit()
// Secondly, do a listing, using the same datadir
clef = runWithKeystore(t, clef.Datadir, "--suppress-bootwarn", "--lightkdf", "list-accounts")
if out := string(clef.Output()); !strings.Contains(out, "0x9160DC9105f7De5dC5E7f3d97ef11DA47269BdA6 (keystore:") {
t.Logf("Output\n%v", out)
t.Error("Failure")
}
})
}
// TestListWallets tests clef --list-wallets
func TestListWallets(t *testing.T) {
t.Parallel()
keyPath := filepath.Join(t.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
t.Run("no-accounts", func(t *testing.T) {
t.Parallel()
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "list-wallets")
if out := string(clef.Output()); !strings.Contains(out, "There are no wallets.") {
t.Logf("Output\n%v", out)
t.Error("Failure")
}
})
t.Run("one-account", func(t *testing.T) {
t.Parallel()
// First, we need to import
clef := runClef(t, "--suppress-bootwarn", "--lightkdf", "importraw", keyPath)
clef.input("myverylongpassword").input("myverylongpassword").WaitExit()
// Secondly, do a listing, using the same datadir
clef = runWithKeystore(t, clef.Datadir, "--suppress-bootwarn", "--lightkdf", "list-wallets")
if out := string(clef.Output()); !strings.Contains(out, "Account 0: 0x9160DC9105f7De5dC5E7f3d97ef11DA47269BdA6") {
t.Logf("Output\n%v", out)
t.Error("Failure")
}
})
}

View file

@ -1,224 +0,0 @@
## UI Client interface
These data types are defined in the channel between clef and the UI
### SignDataRequest
SignDataRequest contains information about a pending request to sign some data. The data to be signed can be of various types, defined by content-type. Clef has done most of the work in canonicalizing and making sense of the data, and it's up to the UI to present the user with the contents of the `message`
Example:
```json
{
"content_type": "text/plain",
"address": "0xDEADbEeF000000000000000000000000DeaDbeEf",
"raw_data": "GUV0aGVyZXVtIFNpZ25lZCBNZXNzYWdlOgoxMWhlbGxvIHdvcmxk",
"messages": [
{
"name": "message",
"value": "\u0019Ethereum Signed Message:\n11hello world",
"type": "text/plain"
}
],
"hash": "0xd9eba16ed0ecae432b71fe008c98cc872bb4cc214d3220a36f365326cf807d68",
"meta": {
"remote": "localhost:9999",
"local": "localhost:8545",
"scheme": "http",
"User-Agent": "Firefox 3.2",
"Origin": "www.malicious.ru"
}
}
```
### SignDataResponse - approve
Response to SignDataRequest
Example:
```json
{
"approved": true
}
```
### SignDataResponse - deny
Response to SignDataRequest
Example:
```json
{
"approved": false
}
```
### SignTxRequest
SignTxRequest contains information about a pending request to sign a transaction. Aside from the transaction itself, there is also a `call_info`-struct. That struct contains messages of various types, that the user should be informed of.
As in any request, it's important to consider that the `meta` info also contains untrusted data.
The `transaction` (on input into clef) can have either `data` or `input` -- if both are set, they must be identical, otherwise an error is generated. However, Clef will always use `data` when passing this struct on (if Clef does otherwise, please file a ticket)
Example:
```json
{
"transaction": {
"from": "0xDEADbEeF000000000000000000000000DeaDbeEf",
"to": null,
"gas": "0x3e8",
"gasPrice": "0x5",
"value": "0x6",
"nonce": "0x1",
"data": "0x01020304"
},
"call_info": [
{
"type": "Warning",
"message": "Something looks odd, show this message as a warning"
},
{
"type": "Info",
"message": "User should see this as well"
}
],
"meta": {
"remote": "localhost:9999",
"local": "localhost:8545",
"scheme": "http",
"User-Agent": "Firefox 3.2",
"Origin": "www.malicious.ru"
}
}
```
### SignTxResponse - approve
Response to request to sign a transaction. This response needs to contain the `transaction`, because the UI is free to make modifications to the transaction.
Example:
```json
{
"transaction": {
"from": "0xDEADbEeF000000000000000000000000DeaDbeEf",
"to": null,
"gas": "0x3e8",
"gasPrice": "0x5",
"value": "0x6",
"nonce": "0x4",
"data": "0x04030201"
},
"approved": true
}
```
### SignTxResponse - deny
Response to SignTxRequest. When denying a request, there's no need to provide the transaction in return
Example:
```json
{
"transaction": {
"from": "0x",
"to": null,
"gas": "0x0",
"gasPrice": "0x0",
"value": "0x0",
"nonce": "0x0",
"data": null
},
"approved": false
}
```
### OnApproved - SignTransactionResult
SignTransactionResult is used in the call `clef` -> `OnApprovedTx(result)`
This occurs _after_ successful completion of the entire signing procedure, but right before the signed transaction is passed to the external caller. This method (and data) can be used by the UI to signal to the user that the transaction was signed, but it is primarily useful for ruleset implementations.
A ruleset that implements a rate limitation needs to know what transactions are sent out to the external interface. By hooking into this methods, the ruleset can maintain track of that count.
**OBS:** Note that if an attacker can restore your `clef` data to a previous point in time (e.g through a backup), the attacker can reset such windows, even if he/she is unable to decrypt the content.
The `OnApproved` method cannot be responded to, it's purely informative
Example:
```json
{
"raw": "0xf85d640101948a8eafb1cf62bfbeb1741769dae1a9dd47996192018026a0716bd90515acb1e68e5ac5867aa11a1e65399c3349d479f5fb698554ebc6f293a04e8a4ebfff434e971e0ef12c5bf3a881b06fd04fc3f8b8a7291fb67a26a1d4ed",
"tx": {
"nonce": "0x64",
"gasPrice": "0x1",
"gas": "0x1",
"to": "0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192",
"value": "0x1",
"input": "0x",
"v": "0x26",
"r": "0x716bd90515acb1e68e5ac5867aa11a1e65399c3349d479f5fb698554ebc6f293",
"s": "0x4e8a4ebfff434e971e0ef12c5bf3a881b06fd04fc3f8b8a7291fb67a26a1d4ed",
"hash": "0x662f6d772692dd692f1b5e8baa77a9ff95bbd909362df3fc3d301aafebde5441"
}
}
```
### UserInputRequest
Sent when clef needs the user to provide data. If 'password' is true, the input field should be treated accordingly (echo-free)
Example:
```json
{
"prompt": "The question to ask the user",
"title": "The title here",
"isPassword": true
}
```
### UserInputResponse
Response to UserInputRequest
Example:
```json
{
"text": "The textual response from user"
}
```
### ListRequest
Sent when a request has been made to list addresses. The UI is provided with the full `account`s, including local directory names. Note: this information is not passed back to the external caller, who only sees the `address`es.
Example:
```json
{
"accounts": [
{
"address": "0xdeadbeef000000000000000000000000deadbeef",
"url": "keystore:///path/to/keyfile/a"
},
{
"address": "0x1111111122222222222233333333334444444444",
"url": "keystore:///path/to/keyfile/b"
}
],
"meta": {
"remote": "localhost:9999",
"local": "localhost:8545",
"scheme": "http",
"User-Agent": "Firefox 3.2",
"Origin": "www.malicious.ru"
}
}
```
### ListResponse
Response to list request. The response contains a list of all addresses to show to the caller. Note: the UI is free to respond with any address the caller, regardless of whether it exists or not
Example:
```json
{
"accounts": [
{
"address": "0x0000000000000000000000000000000000000000",
"url": ".. ignored .."
},
{
"address": "0xffffffffffffffffffffffffffffffffffffffff",
"url": ""
}
]
}
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View file

@ -1,23 +0,0 @@
"""
This implements a dispatcher which listens to localhost:8550, and proxies
requests via qrexec to the service qubes.EthSign on a target domain
"""
import http.server
import socketserver,subprocess
PORT=8550
TARGET_DOMAIN= 'debian-work'
class Dispatcher(http.server.BaseHTTPRequestHandler):
def do_POST(self):
post_data = self.rfile.read(int(self.headers['Content-Length']))
p = subprocess.Popen(['/usr/bin/qrexec-client-vm',TARGET_DOMAIN,'qubes.Clefsign'],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output = p.communicate(post_data)[0]
self.wfile.write(output)
with socketserver.TCPServer(("",PORT), Dispatcher) as httpd:
print("Serving at port", PORT)
httpd.serve_forever()

View file

@ -1,16 +0,0 @@
#!/bin/bash
SIGNER_BIN="/home/user/tools/clef/clef"
SIGNER_CMD="/home/user/tools/gtksigner/gtkui.py -s $SIGNER_BIN"
# Start clef if not already started
if [ ! -S /home/user/.clef/clef.ipc ]; then
$SIGNER_CMD &
sleep 1
fi
# Should be started by now
if [ -S /home/user/.clef/clef.ipc ]; then
# Post incoming request to HTTP channel
curl -H "Content-Type: application/json" -X POST -d @- http://localhost:8550 2>/dev/null
fi

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View file

@ -1,198 +0,0 @@
# Setting up Clef
This document describes how Clef can be used in a more secure manner than executing it from your everyday laptop,
in order to ensure that the keys remain safe in the event that your computer should get compromised.
## Qubes OS
### Background
The Qubes operating system is based around virtual machines (qubes), where a set of virtual machines are configured, typically for
different purposes such as:
- personal
- Your personal email, browsing etc
- work
- Work email etc
- vault
- a VM without network access, where gpg-keys and/or keepass credentials are stored.
A couple of dedicated virtual machines handle externalities:
- sys-net provides networking to all other (network-enabled) machines
- sys-firewall handles firewall rules
- sys-usb handles USB devices, and can map usb-devices to certain qubes.
The goal of this document is to describe how we can set up clef to provide secure transaction
signing from a `vault` vm, to another networked qube which runs Dapps.
### Setup
There are two ways that this can be achieved: integrated via Qubes or integrated via networking.
#### 1. Qubes Integrated
Qubes provides a facility for inter-qubes communication via `qrexec`. A qube can request to make a cross-qube RPC request
to another qube. The OS then asks the user if the call is permitted.
![Example](qubes/qrexec-example.png)
A policy-file can be created to allow such interaction. On the `target` domain, a service is invoked which can read the
`stdin` from the `client` qube.
This is how [Split GPG](https://www.qubes-os.org/doc/split-gpg/) is implemented. We can set up Clef the same way:
##### Server
![Clef via qrexec](qubes/clef_qubes_qrexec.png)
On the `target` qubes, we need to define the RPC service.
[qubes.Clefsign](qubes/qubes.Clefsign):
```bash
#!/bin/bash
SIGNER_BIN="/home/user/tools/clef/clef"
SIGNER_CMD="/home/user/tools/gtksigner/gtkui.py -s $SIGNER_BIN"
# Start clef if not already started
if [ ! -S /home/user/.clef/clef.ipc ]; then
$SIGNER_CMD &
sleep 1
fi
# Should be started by now
if [ -S /home/user/.clef/clef.ipc ]; then
# Post incoming request to HTTP channel
curl -H "Content-Type: application/json" -X POST -d @- http://localhost:8550 2>/dev/null
fi
```
This RPC service is not complete (see notes about HTTP headers below), but works as a proof-of-concept.
It will forward the data received on `stdin` (forwarded by the OS) to Clef's HTTP channel.
It would have been possible to send data directly to the `/home/user/.clef/.clef.ipc`
socket via e.g `nc -U /home/user/.clef/clef.ipc`, but the reason for sending the request
data over `HTTP` instead of `IPC` is that we want the ability to forward `HTTP` headers.
To enable the service:
``` bash
sudo cp qubes.Clefsign /etc/qubes-rpc/
sudo chmod +x /etc/qubes-rpc/ qubes.Clefsign
```
This setup uses [gtksigner](https://github.com/holiman/gtksigner), which is a very minimal GTK-based UI that works well
with minimal requirements.
##### Client
On the `client` qube, we need to create a listener which will receive the request from the Dapp, and proxy it.
[qubes-client.py](qubes/qubes-client.py):
```python
"""
This implements a dispatcher which listens to localhost:8550, and proxies
requests via qrexec to the service qubes.EthSign on a target domain
"""
import http.server
import socketserver,subprocess
PORT=8550
TARGET_DOMAIN= 'debian-work'
class Dispatcher(http.server.BaseHTTPRequestHandler):
def do_POST(self):
post_data = self.rfile.read(int(self.headers['Content-Length']))
p = subprocess.Popen(['/usr/bin/qrexec-client-vm',TARGET_DOMAIN,'qubes.Clefsign'],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output = p.communicate(post_data)[0]
self.wfile.write(output)
with socketserver.TCPServer(("",PORT), Dispatcher) as httpd:
print("Serving at port", PORT)
httpd.serve_forever()
```
#### Testing
To test the flow, if we have set up `debian-work` as the `target`, we can do
```bash
$ cat newaccnt.json
{ "id": 0, "jsonrpc": "2.0","method": "account_new","params": []}
$ cat newaccnt.json| qrexec-client-vm debian-work qubes.Clefsign
```
A dialog should pop up first to allow the IPC call:
![one](qubes/qubes_newaccount-1.png)
Followed by a GTK-dialog to approve the operation:
![two](qubes/qubes_newaccount-2.png)
To test the full flow, we use the client wrapper. Start it on the `client` qube:
```
[user@work qubes]$ python3 qubes-client.py
```
Make the request over http (`client` qube):
```
[user@work clef]$ cat newaccnt.json | curl -X POST -d @- http://localhost:8550
```
And it should show the same popups again.
##### Pros and cons
The benefits of this setup are:
- This is the qubes-os intended model for inter-qube communication,
- and thus benefits from qubes-os dialogs and policies for user approval
However, it comes with a couple of drawbacks:
- The `qubes-gpg-client` must forward the http request via RPC to the `target` qube. When doing so, the proxy
will either drop important headers, or replace them.
- The `Host` header is most likely `localhost`
- The `Origin` header must be forwarded
- Information about the remote ip must be added as a `X-Forwarded-For`. However, Clef cannot always trust an `XFF` header,
since malicious clients may lie about `XFF` in order to fool the http server into believing it comes from another address.
- Even with a policy in place to allow RPC calls between `caller` and `target`, there will be several popups:
- One qubes-specific where the user specifies the `target` vm
- One clef-specific to approve the transaction
#### 2. Network integrated
The second way to set up Clef on a qubes system is to allow networking, and have Clef listen to a port which is accessible
from other qubes.
![Clef via http](qubes/clef_qubes_http.png)
## USBArmory
The [USB armory](https://inversepath.com/usbarmory) is an open source hardware design with an 800 MHz ARM processor. It is a pocket-size
computer. When inserted into a laptop, it identifies itself as a USB network interface, basically adding another network
to your computer. Over this new network interface, you can SSH into the device.
Running Clef off a USB armory means that you can use the armory as a very versatile offline computer, which only
ever connects to a local network between your computer and the device itself.
Needless to say, while this model should be fairly secure against remote attacks, an attacker with physical access
to the USB Armory would trivially be able to extract the contents of the device filesystem.

View file

@ -1,104 +0,0 @@
## Changelog for external API
The API uses [semantic versioning](https://semver.org/).
TL;DR: Given a version number MAJOR.MINOR.PATCH, increment the:
* MAJOR version when you make incompatible API changes,
* MINOR version when you add functionality in a backwards-compatible manner, and
* PATCH version when you make backwards-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
### 6.1.0
The API-method `account_signGnosisSafeTx` was added. This method takes two parameters,
`[address, safeTx]`. The latter, `safeTx`, can be copy-pasted from the gnosis relay. For example:
```
{
"jsonrpc": "2.0",
"method": "account_signGnosisSafeTx",
"params": ["0xfd1c4226bfD1c436672092F4eCbfC270145b7256",
{
"safe": "0x25a6c4BBd32B2424A9c99aEB0584Ad12045382B3",
"to": "0xB372a646f7F05Cc1785018dBDA7EBc734a2A20E2",
"value": "20000000000000000",
"data": null,
"operation": 0,
"gasToken": "0x0000000000000000000000000000000000000000",
"safeTxGas": 27845,
"baseGas": 0,
"gasPrice": "0",
"refundReceiver": "0x0000000000000000000000000000000000000000",
"nonce": 2,
"executionDate": null,
"submissionDate": "2020-09-15T21:54:49.617634Z",
"modified": "2020-09-15T21:54:49.617634Z",
"blockNumber": null,
"transactionHash": null,
"safeTxHash": "0x2edfbd5bc113ff18c0631595db32eb17182872d88d9bf8ee4d8c2dd5db6d95e2",
"executor": null,
"isExecuted": false,
"isSuccessful": null,
"ethGasPrice": null,
"gasUsed": null,
"fee": null,
"origin": null,
"dataDecoded": null,
"confirmationsRequired": null,
"confirmations": [
{
"owner": "0xAd2e180019FCa9e55CADe76E4487F126Fd08DA34",
"submissionDate": "2020-09-15T21:54:49.663299Z",
"transactionHash": null,
"confirmationType": "CONFIRMATION",
"signature": "0x95a7250bb645f831c86defc847350e7faff815b2fb586282568e96cc859e39315876db20a2eed5f7a0412906ec5ab57652a6f645ad4833f345bda059b9da2b821c",
"signatureType": "EOA"
}
],
"signatures": null
}
],
"id": 67
}
```
Not all fields are required, though. This method is really just a UX helper, which massages the
input to conform to the `EIP-712` [specification](https://docs.safe.global/core-api/transaction-service-reference/gnosis)
for the Gnosis Safe, and making the output be directly importable to by a relay service.
### 6.0.0
* `New` was changed to deliver only an address, not the full `Account` data
* `Export` was moved from External API to the UI Server API
#### 5.0.0
* The external `account_EcRecover`-method was reimplemented.
* The external method `account_sign(address, data)` was replaced with `account_signData(contentType, address, data)`.
The addition of `contentType` makes it possible to use the method for different types of objects, such as:
* signing data with an intended validator (not yet implemented)
* signing clique headers,
* signing plain personal messages,
* The external method `account_signTypedData` implements [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) and makes it possible to sign typed data.
#### 4.0.0
* The external `account_Ecrecover`-method was removed.
* The external `account_Import`-method was removed.
#### 3.0.0
* The external `account_List`-method was changed to not expose `url`, which contained info about the local filesystem. It now returns only a list of addresses.
#### 2.0.0
* Commit `73abaf04b1372fa4c43201fb1b8019fe6b0a6f8d`, move `from` into `transaction` object in `signTransaction`. This
makes the `accounts_signTransaction` identical to the old `eth_signTransaction`.
#### 1.0.0
Initial release.

View file

@ -1,191 +0,0 @@
## Changelog for internal API (ui-api)
The API uses [semantic versioning](https://semver.org/).
TL;DR: Given a version number MAJOR.MINOR.PATCH, increment the:
* MAJOR version when you make incompatible API changes,
* MINOR version when you add functionality in a backwards-compatible manner, and
* PATCH version when you make backwards-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
### 7.0.1
Added `clef_New` to the internal API callable from a UI.
> `New` creates a new password protected Account. The private key is protected with
> the given password. Users are responsible to backup the private key that is stored
> in the keystore location that was specified when this API was created.
> This method is the same as New on the external API, the difference being that
> this implementation does not ask for confirmation, since it's initiated by
> the user
### 7.0.0
- The `message` field was renamed to `messages` in all data signing request methods to better reflect that it's a list, not a value.
- The `storage.Put` and `storage.Get` methods in the rule execution engine were lower-cased to `storage.put` and `storage.get` to be consistent with JavaScript call conventions.
### 6.0.0
Removed `password` from responses to operations which require them. This is for two reasons,
- Consistency between how rulesets operate and how manual processing works. A rule can `Approve` but require the actual password to be stored in the clef storage.
With this change, the same stored password can be used even if rulesets are not enabled, but storage is.
- It also removes the usability-shortcut that a UI might otherwise want to implement; remembering passwords. Since we now will not require the
password on every `Approve`, there's no need for the UI to cache it locally.
- In a future update, we'll likely add `clef_storePassword` to the internal API, so the user can store it via his UI (currently only CLI works).
Affected datatypes:
- `SignTxResponse`
- `SignDataResponse`
- `NewAccountResponse`
If `clef` requires a password, the `OnInputRequired` will be used to collect it.
### 5.0.0
Changed the namespace format to adhere to the legacy ethereum format: `name_methodName`. Changes:
* `ApproveTx` -> `ui_approveTx`
* `ApproveSignData` -> `ui_approveSignData`
* `ApproveExport` -> `removed`
* `ApproveImport` -> `removed`
* `ApproveListing` -> `ui_approveListing`
* `ApproveNewAccount` -> `ui_approveNewAccount`
* `ShowError` -> `ui_showError`
* `ShowInfo` -> `ui_showInfo`
* `OnApprovedTx` -> `ui_onApprovedTx`
* `OnSignerStartup` -> `ui_onSignerStartup`
* `OnInputRequired` -> `ui_onInputRequired`
### 4.0.0
* Bidirectional communication implemented, so the UI can query `clef` via the stdin/stdout RPC channel. Methods implemented are:
- `clef_listWallets`
- `clef_listAccounts`
- `clef_listWallets`
- `clef_deriveAccount`
- `clef_importRawKey`
- `clef_openWallet`
- `clef_chainId`
- `clef_setChainId`
- `clef_export`
- `clef_import`
* The type `Account` was modified (the json-field `type` was removed), to consist of
```go
type Account struct {
Address common.Address `json:"address"` // Ethereum account address derived from the key
URL URL `json:"url"` // Optional resource locator within a backend
}
```
### 3.2.0
* Make `ShowError`, `OnApprovedTx`, `OnSignerStartup` be json-rpc [notifications](https://www.jsonrpc.org/specification#notification):
> A Notification is a Request object without an "id" member. A Request object that is a Notification signifies the Client's lack of interest in the corresponding Response object, and as such no Response object needs to be returned to the client. The Server MUST NOT reply to a Notification, including those that are within a batch request.
>
> Notifications are not confirmable by definition, since they do not have a Response object to be returned. As such, the Client would not be aware of any errors (like e.g. "Invalid params","Internal error"
### 3.1.0
* Add `ContentType` `string` to `SignDataRequest` to accommodate the latest [EIP-191](https://eips.ethereum.org/EIPS/eip-191) and [EIP-712](https://eips.ethereum.org/EIPS/eip-712) implementations.
### 3.0.0
* Make use of `OnInputRequired(info UserInputRequest)` for obtaining master password during startup
### 2.1.0
* Add `OnInputRequired(info UserInputRequest)` to internal API. This method is used when Clef needs user input, e.g. passwords.
The following structures are used:
```go
UserInputRequest struct {
Prompt string `json:"prompt"`
Title string `json:"title"`
IsPassword bool `json:"isPassword"`
}
UserInputResponse struct {
Text string `json:"text"`
}
```
### 2.0.0
* Modify how `call_info` on a transaction is conveyed. New format:
```
{
"jsonrpc": "2.0",
"id": 2,
"method": "ApproveTx",
"params": [
{
"transaction": {
"from": "0x82A2A876D39022B3019932D30Cd9c97ad5616813",
"to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0",
"gas": "0x333",
"gasPrice": "0x123",
"value": "0x10",
"nonce": "0x0",
"data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012",
"input": null
},
"call_info": [
{
"type": "WARNING",
"message": "Invalid checksum on to-address"
},
{
"type": "WARNING",
"message": "Tx contains data, but provided ABI signature could not be matched: Did not match: test (0 matches)"
}
],
"meta": {
"remote": "127.0.0.1:54286",
"local": "localhost:8550",
"scheme": "HTTP/1.1"
}
}
]
}
```
#### 1.2.0
* Add `OnStartup` method, to provide the UI with information about what API version
the signer uses (both internal and external) as well as build-info and external api.
Example call:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "OnSignerStartup",
"params": [
{
"info": {
"extapi_http": "http://localhost:8550",
"extapi_ipc": null,
"extapi_version": "2.0.0",
"intapi_version": "1.2.0"
}
}
]
}
```
#### 1.1.0
* Add `OnApproved` method
#### 1.0.0
Initial release.

File diff suppressed because it is too large Load diff

View file

@ -1,315 +0,0 @@
import sys
import subprocess
from tinyrpc.transports import ServerTransport
from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
from tinyrpc.dispatch import public, RPCDispatcher
from tinyrpc.server import RPCServer
"""
This is a POC example of how to write a custom UI for Clef.
The UI starts the clef process with the '--stdio-ui' option
and communicates with clef using standard input / output.
The standard input/output is a relatively secure way to communicate,
as it does not require opening any ports or IPC files. Needless to say,
it does not protect against memory inspection mechanisms
where an attacker can access process memory.
To make this work install all the requirements:
pip install -r requirements.txt
"""
try:
import urllib.parse as urlparse
except ImportError:
import urllib as urlparse
class StdIOTransport(ServerTransport):
"""Uses std input/output for RPC"""
def receive_message(self):
return None, urlparse.unquote(sys.stdin.readline())
def send_reply(self, context, reply):
print(reply)
class PipeTransport(ServerTransport):
"""Uses std a pipe for RPC"""
def __init__(self, input, output):
self.input = input
self.output = output
def receive_message(self):
data = self.input.readline()
print(">> {}".format(data))
return None, urlparse.unquote(data)
def send_reply(self, context, reply):
reply = str(reply, "utf-8")
print("<< {}".format(reply))
self.output.write("{}\n".format(reply))
def sanitize(txt, limit=100):
return txt[:limit].encode("unicode_escape").decode("utf-8")
def metaString(meta):
"""
"meta":{"remote":"clef binary","local":"main","scheme":"in-proc","User-Agent":"","Origin":""}
""" # noqa: E501
message = (
"\tRequest context:\n"
"\t\t{remote} -> {scheme} -> {local}\n"
"\tAdditional HTTP header data, provided by the external caller:\n"
"\t\tUser-Agent: {user_agent}\n"
"\t\tOrigin: {origin}\n"
)
return message.format(
remote=meta.get("remote", "<missing>"),
scheme=meta.get("scheme", "<missing>"),
local=meta.get("local", "<missing>"),
user_agent=sanitize(meta.get("User-Agent"), 200),
origin=sanitize(meta.get("Origin"), 100),
)
class StdIOHandler:
def __init__(self):
pass
@public
def approveTx(self, req):
"""
Example request:
{"jsonrpc":"2.0","id":20,"method":"ui_approveTx","params":[{"transaction":{"from":"0xDEADbEeF000000000000000000000000DeaDbeEf","to":"0xDEADbEeF000000000000000000000000DeaDbeEf","gas":"0x3e8","gasPrice":"0x5","maxFeePerGas":null,"maxPriorityFeePerGas":null,"value":"0x6","nonce":"0x1","data":"0x"},"call_info":null,"meta":{"remote":"clef binary","local":"main","scheme":"in-proc","User-Agent":"","Origin":""}}]}
:param transaction: transaction info
:param call_info: info about the call, e.g. if ABI info could not be
:param meta: metadata about the request, e.g. where the call comes from
:return:
""" # noqa: E501
message = (
"Sign transaction request:\n"
"\t{meta_string}\n"
"\n"
"\tFrom: {from_}\n"
"\tTo: {to}\n"
"\n"
"\tAuto-rejecting request"
)
meta = req.get("meta", {})
transaction = req.get("transaction")
sys.stdout.write(
message.format(
meta_string=metaString(meta),
from_=transaction.get("from", "<missing>"),
to=transaction.get("to", "<missing>"),
)
)
return {
"approved": False,
}
@public
def approveSignData(self, req):
"""
Example request:
{"jsonrpc":"2.0","id":8,"method":"ui_approveSignData","params":[{"content_type":"application/x-clique-header","address":"0x0011223344556677889900112233445566778899","raw_data":"+QIRoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIIFOYIFOYIFOoIFOoIFOppFeHRyYSBkYXRhIEV4dHJhIGRhdGEgRXh0cqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIgAAAAAAAAAAA==","messages":[{"name":"Clique header","value":"clique header 1337 [0x44381ab449d77774874aca34634cb53bc21bd22aef2d3d4cf40e51176cb585ec]","type":"clique"}],"call_info":null,"hash":"0xa47ab61438a12a06c81420e308c2b7aae44e9cd837a5df70dd021421c0f58643","meta":{"remote":"clef binary","local":"main","scheme":"in-proc","User-Agent":"","Origin":""}}]}
""" # noqa: E501
message = (
"Sign data request:\n"
"\t{meta_string}\n"
"\n"
"\tContent-type: {content_type}\n"
"\tAddress: {address}\n"
"\tHash: {hash_}\n"
"\n"
"\tAuto-rejecting request\n"
)
meta = req.get("meta", {})
sys.stdout.write(
message.format(
meta_string=metaString(meta),
content_type=req.get("content_type"),
address=req.get("address"),
hash_=req.get("hash"),
)
)
return {
"approved": False,
"password": None,
}
@public
def approveNewAccount(self, req):
"""
Example request:
{"jsonrpc":"2.0","id":25,"method":"ui_approveNewAccount","params":[{"meta":{"remote":"clef binary","local":"main","scheme":"in-proc","User-Agent":"","Origin":""}}]}
""" # noqa: E501
message = (
"Create new account request:\n"
"\t{meta_string}\n"
"\n"
"\tAuto-rejecting request\n"
)
meta = req.get("meta", {})
sys.stdout.write(message.format(meta_string=metaString(meta)))
return {
"approved": False,
}
@public
def showError(self, req):
"""
Example request:
{"jsonrpc":"2.0","method":"ui_showError","params":[{"text":"If you see this message, enter 'yes' to the next question"}]}
:param message: to display
:return:nothing
""" # noqa: E501
message = (
"## Error\n{text}\n"
"Press enter to continue\n"
)
text = req.get("text")
sys.stdout.write(message.format(text=text))
input()
return
@public
def showInfo(self, req):
"""
Example request:
{"jsonrpc":"2.0","method":"ui_showInfo","params":[{"text":"If you see this message, enter 'yes' to next question"}]}
:param message: to display
:return:nothing
""" # noqa: E501
message = (
"## Info\n{text}\n"
"Press enter to continue\n"
)
text = req.get("text")
sys.stdout.write(message.format(text=text))
input()
return
@public
def onSignerStartup(self, req):
"""
Example request:
{"jsonrpc":"2.0", "method":"ui_onSignerStartup", "params":[{"info":{"extapi_http":"n/a","extapi_ipc":"/home/user/.clef/clef.ipc","extapi_version":"6.1.0","intapi_version":"7.0.1"}}]}
""" # noqa: E501
message = (
"\n"
"\t\tExt api url: {extapi_http}\n"
"\t\tInt api ipc: {extapi_ipc}\n"
"\t\tExt api ver: {extapi_version}\n"
"\t\tInt api ver: {intapi_version}\n"
)
info = req.get("info")
sys.stdout.write(
message.format(
extapi_http=info.get("extapi_http"),
extapi_ipc=info.get("extapi_ipc"),
extapi_version=info.get("extapi_version"),
intapi_version=info.get("intapi_version"),
)
)
@public
def approveListing(self, req):
"""
Example request:
{"jsonrpc":"2.0","id":23,"method":"ui_approveListing","params":[{"accounts":[{"address":...
""" # noqa: E501
message = (
"\n"
"## Account listing request\n"
"\t{meta_string}\n"
"\tDo you want to allow listing the following accounts?\n"
"\t-{addrs}\n"
"\n"
"->Auto-answering No\n"
)
meta = req.get("meta", {})
accounts = req.get("accounts", [])
addrs = [x.get("address") for x in accounts]
sys.stdout.write(
message.format(
addrs="\n\t-".join(addrs),
meta_string=metaString(meta)
)
)
return {}
@public
def onInputRequired(self, req):
"""
Example request:
{"jsonrpc":"2.0","id":1,"method":"ui_onInputRequired","params":[{"title":"Master Password","prompt":"Please enter the password to decrypt the master seed","isPassword":true}]}
:param message: to display
:return:nothing
""" # noqa: E501
message = (
"\n"
"## {title}\n"
"\t{prompt}\n"
"\n"
"> "
)
sys.stdout.write(
message.format(
title=req.get("title"),
prompt=req.get("prompt")
)
)
isPassword = req.get("isPassword")
if not isPassword:
return {"text": input()}
return ""
def main(args):
cmd = ["clef", "--stdio-ui"]
if len(args) > 0 and args[0] == "test":
cmd.extend(["--stdio-ui-test"])
print("cmd: {}".format(" ".join(cmd)))
dispatcher = RPCDispatcher()
dispatcher.register_instance(StdIOHandler(), "ui_")
# line buffered
p = subprocess.Popen(
cmd,
bufsize=1,
universal_newlines=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
rpc_server = RPCServer(
PipeTransport(p.stdout, p.stdin), JSONRPCProtocol(), dispatcher
)
rpc_server.serve_forever()
if __name__ == "__main__":
main(sys.argv[1:])

View file

@ -1 +0,0 @@
tinyrpc==1.1.4

View file

@ -1,234 +0,0 @@
# Rules
The `signer` binary contains a ruleset engine, implemented with [OttoVM](https://github.com/robertkrimen/otto)
It enables use cases like the following:
* I want to auto-approve transactions with contract `CasinoDapp`, with up to `0.05 ether` in value to maximum `1 ether` per 24h period
* I want to auto-approve transaction to contract `EthAlarmClock` with `data`=`0xdeadbeef`, if `value=0`, `gas < 44k` and `gasPrice < 40Gwei`
The two main features that are required for this to work well are:
1. Rule Implementation: how to create, manage, and interpret rules in a flexible but secure manner
2. Credential management and credentials; how to provide auto-unlock without exposing keys unnecessarily.
The section below deals with both of them
## Rule Implementation
A ruleset file is implemented as a `js` file. Under the hood, the ruleset engine is a `SignerUI`, implementing the same methods as the `json-rpc` methods
defined in the UI protocol. Example:
```js
function asBig(str) {
if (str.slice(0, 2) == "0x") {
return new BigNumber(str.slice(2), 16)
}
return new BigNumber(str)
}
// Approve transactions to a certain contract if the value is below a certain limit
function ApproveTx(req) {
var limit = new BigNumber("0xb1a2bc2ec50000")
var value = asBig(req.transaction.value);
if (req.transaction.to.toLowerCase() == "0xae967917c465db8578ca9024c205720b1a3651a9" && value.lt(limit)) {
return "Approve"
}
// If we return "Reject", it will be rejected.
// By not returning anything, it will be passed to the next UI, for manual processing
}
// Approve listings if request made from IPC
function ApproveListing(req){
if (req.metadata.scheme == "ipc"){ return "Approve"}
}
```
Whenever the external API is called (and the ruleset is enabled), the `signer` calls the UI, which is an instance of a ruleset-engine. The ruleset-engine
invokes the corresponding method. In doing so, there are three possible outcomes:
1. JS returns "Approve"
* Auto-approve request
2. JS returns "Reject"
* Auto-reject request
3. Error occurs, or something else is returned
* Pass on to `next` ui: the regular UI channel.
A more advanced example can be found below, "Example 1: ruleset for a rate-limited window", using `storage` to `Put` and `Get` `string`s by key.
* At the time of writing, storage only exists as an ephemeral unencrypted implementation, to be used during testing.
### Things to note
The Otto vm has a few [caveats](https://github.com/robertkrimen/otto):
* "use strict" will parse, but does nothing.
* The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification.
* Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported.
Additionally, a few more have been added
* The rule execution cannot load external javascript files.
* The only preloaded library is [`bignumber.js`](https://github.com/MikeMcl/bignumber.js) version `2.0.3`. This one is fairly old, and is not aligned with the documentation at the GitHub repository.
* Each invocation is made in a fresh virtual machine. This means that you cannot store data in global variables between invocations. This is a deliberate choice -- if you want to store data, use the disk-backed `storage`, since rules should not rely on ephemeral data.
* Javascript API parameters are _always_ an object. This is also a design choice, to ensure that parameters are accessed by _key_ and not by order. This is to prevent mistakes due to missing parameters or parameter changes.
* The JS engine has access to `storage` and `console`.
#### Security considerations
##### Security of ruleset
Some security precautions can be made, such as:
* Never load `ruleset.js` unless the file is `readonly` (`r-??-??-?`). If the user wishes to modify the ruleset, he must make it writeable and then set back to readonly.
* This is to prevent attacks where files are dropped on the users disk.
* Since we're going to have to have some form of secure storage (not defined in this section), we could also store the `sha3` of the `ruleset.js` file in there.
* If the user wishes to modify the ruleset, he'd then have to perform e.g. `signer --attest /path/to/ruleset --credential <creds>`
##### Security of implementation
The drawback of this very flexible solution is that the `signer` needs to contain a javascript engine. This is pretty simple to implement since it's already
implemented for `geth`. There are no known security vulnerabilities in it, nor have we had any security problems with it so far.
The javascript engine would be an added attack surface; but if the validation of `rulesets` is made good (with hash-based attestation), the actual javascript cannot be considered
an attack surface -- if an attacker can control the ruleset, a much simpler attack would be to implement an "always-approve" rule instead of exploiting the js vm. The only benefit
to be gained from attacking the actual `signer` process from the `js` side would be if it could somehow extract cryptographic keys from memory.
##### Security in usability
Javascript is flexible, but also easy to get wrong, especially when users assume that `js` can handle large integers natively. Typical errors
include trying to multiply `gasCost` with `gas` without using `bigint`:s.
It's unclear whether any other DSL could be more secure; since there's always the possibility of erroneously implementing a rule.
## Credential management
The ability to auto-approve transactions means that the signer needs to have the necessary credentials to decrypt keyfiles. These passwords are hereafter called `ksp` (keystore pass).
### Example implementation
Upon startup of the signer, the signer is given a switch: `--seed <path/to/masterseed>`
The `seed` contains a blob of bytes, which is the master seed for the `signer`.
The `signer` uses the `seed` to:
* Generate the `path` where the settings are stored.
* `./settings/1df094eb-c2b1-4689-90dd-790046d38025/vault.dat`
* `./settings/1df094eb-c2b1-4689-90dd-790046d38025/rules.js`
* Generate the encryption password for `vault.dat`.
The `vault.dat` would be an encrypted container storing the following information:
* `ksp` entries
* `sha256` hash of `rules.js`
* Information about pair:ed callers (not yet specified)
### Security considerations
This would leave it up to the user to ensure that the `path/to/masterseed` is handled securely. It's difficult to get around this, although one could
imagine leveraging OS-level keychains where supported. The setup is however, in general, similar to how ssh-keys are stored in `.ssh/`.
# Implementation status
This is now implemented (with ephemeral non-encrypted storage for now, so not yet enabled).
## Example 1: ruleset for a rate-limited window
```js
function big(str) {
if (str.slice(0, 2) == "0x") {
return new BigNumber(str.slice(2), 16)
}
return new BigNumber(str)
}
// Time window: 1 week
var window = 1000* 3600*24*7;
// Limit: 1 ether
var limit = new BigNumber("1e18");
function isLimitOk(transaction) {
var value = big(transaction.value)
// Start of our window function
var windowstart = new Date().getTime() - window;
var txs = [];
var stored = storage.get('txs');
if (stored != "") {
txs = JSON.parse(stored)
}
// First, remove all that has passed out of the time window
var newtxs = txs.filter(function(tx){return tx.tstamp > windowstart});
console.log(txs, newtxs.length);
// Secondly, aggregate the current sum
sum = new BigNumber(0)
sum = newtxs.reduce(function(agg, tx){ return big(tx.value).plus(agg)}, sum);
console.log("ApproveTx > Sum so far", sum);
console.log("ApproveTx > Requested", value.toNumber());
// Would we exceed the weekly limit ?
return sum.plus(value).lt(limit)
}
function ApproveTx(r) {
if (isLimitOk(r.transaction)) {
return "Approve"
}
return "Nope"
}
/**
* OnApprovedTx(str) is called when a transaction has been approved and signed. The parameter
* 'response_str' contains the return value that will be sent to the external caller.
* The return value from this method is ignore - the reason for having this callback is to allow the
* ruleset to keep track of approved transactions.
*
* When implementing rate-limited rules, this callback should be used.
* If a rule responds with neither 'Approve' nor 'Reject' - the tx goes to manual processing. If the user
* then accepts the transaction, this method will be called.
*
* TLDR; Use this method to keep track of signed transactions, instead of using the data in ApproveTx.
*/
function OnApprovedTx(resp) {
var value = big(resp.tx.value)
var txs = []
// Load stored transactions
var stored = storage.get('txs');
if (stored != "") {
txs = JSON.parse(stored)
}
// Add this to the storage
txs.push({tstamp: new Date().getTime(), value: value});
storage.put("txs", JSON.stringify(txs));
}
```
## Example 2: allow destination
```js
function ApproveTx(r) {
if (r.transaction.from.toLowerCase() == "0x0000000000000000000000000000000000001337") {
return "Approve"
}
if (r.transaction.from.toLowerCase() == "0x000000000000000000000000000000000000dead") {
return "Reject"
}
// Otherwise goes to manual processing
}
```
## Example 3: Allow listing
```js
function ApproveListing() {
return "Approve"
}
```

View file

@ -1,103 +0,0 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"fmt"
"os"
"testing"
"github.com/ethereum/go-ethereum/internal/cmdtest"
"github.com/ethereum/go-ethereum/internal/reexec"
)
const registeredName = "clef-test"
type testproc struct {
*cmdtest.TestCmd
// template variables for expect
Datadir string
Etherbase string
}
func init() {
reexec.Register(registeredName, func() {
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
os.Exit(0)
})
}
func TestMain(m *testing.M) {
// check if we have been reexec'd
if reexec.Init() {
return
}
os.Exit(m.Run())
}
// runClef spawns clef with the given command line args and adds keystore arg.
// This method creates a temporary keystore folder which will be removed after
// the test exits.
func runClef(t *testing.T, args ...string) *testproc {
ddir := t.TempDir()
return runWithKeystore(t, ddir, args...)
}
// runWithKeystore spawns clef with the given command line args and adds keystore arg.
// This method does _not_ create the keystore folder, but it _does_ add the arg
// to the args.
func runWithKeystore(t *testing.T, keystore string, args ...string) *testproc {
args = append([]string{"--keystore", keystore}, args...)
tt := &testproc{Datadir: keystore}
tt.TestCmd = cmdtest.NewTestCmd(t, tt)
// Boot "clef". This actually runs the test binary but the TestMain
// function will prevent any tests from running.
tt.Run(registeredName, args...)
return tt
}
func (proc *testproc) input(text string) *testproc {
proc.TestCmd.InputLine(text)
return proc
}
/*
// waitForEndpoint waits for the rpc endpoint to appear, or
// aborts after 3 seconds.
func (proc *testproc) waitForEndpoint(t *testing.T) *testproc {
t.Helper()
timeout := 3 * time.Second
ipc := filepath.Join(proc.Datadir, "clef.ipc")
start := time.Now()
for time.Since(start) < timeout {
if _, err := os.Stat(ipc); !errors.Is(err, os.ErrNotExist) {
t.Logf("endpoint %v opened", ipc)
return proc
}
time.Sleep(200 * time.Millisecond)
}
t.Logf("stderr: \n%v", proc.StderrText())
t.Logf("stdout: \n%v", proc.Output())
t.Fatal("endpoint", ipc, "did not open within", timeout)
return proc
}
*/

Some files were not shown because too many files have changed in this diff Show more