Compare commits

...

19 Commits

Author SHA1 Message Date
levisyin e7543876db
fix: process conflict in windows 2025-02-19 23:30:37 +08:00
levisyin 445db5614d
Merge branch 'ethereum:master' into fix/linter-usetesting 2025-02-19 18:23:09 +08:00
levisyin 07d7fe2b33
build: upgrade -dlgo version to Go 1.24.0 (#31159)
Co-authored-by: Felix Lange <fjl@twurst.com>
2025-02-19 11:21:22 +01:00
Matthieu Vachon dab746b3ef
eth/catalyst: support earlier forks in SimulatedBeacon (#31084)
Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
2025-02-18 21:08:43 +01:00
Marius van der Wijden ef00a6e9a2
params: add osaka blob schedule (#31174)
Prevents crashes when running execution spec tests for osaka
2025-02-18 15:03:48 +01:00
rjl493456442 32c6aa8a1a
core/vm: clean up EVM environmental structure (#31061)
This PR does a few things including:

- Remove `ContractRef` interface
- Remove `vm.AccountRef` which implements `ContractRef` interface
- Maintain the `jumpDests` struct in EVM for sharing between call frames
- Simplify the delegateCall context initialization
2025-02-18 21:53:33 +08:00
EdisonSR 7332a1bc0a
ethclient: add comment describing block number tags (#30984)
Adds a comment on how to use rpc.*BlockNumber and the explanation of the block number tags

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2025-02-18 11:15:36 +01:00
piersy 68d477670c
utils: clarify description for history.state flag (#31164) 2025-02-18 13:50:19 +08:00
Marius van der Wijden 3adfa1fbeb
trie: do not expect ordering in stacktrie during fuzzing (#31170)
This PR removes the assumption of the stacktrie and trie to have the
same ordering. This was hit by the fuzzers on oss-fuzz

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
2025-02-18 10:48:42 +08:00
Felix Lange aec1964410 version: begin v1.15.3 release cycle 2025-02-17 12:01:20 +01:00
Felix Lange c8c62dafc7 version: release go-ethereum v1.15.2 stable 2025-02-17 11:59:48 +01:00
Felix Lange d37a0b8cd0
eth/protocols/eth: add discovery iterator to protocol (#31185)
We somehow forgot to add this in #30302, so discv5 and DNS have actually
been disabled since then.

Fixes #31168
2025-02-17 10:12:03 +01:00
Felix Lange c113e3b5b1
p2p: fix marshaling of NAT in TOML (#31192)
This fixes an issue where a nat.Interface unmarshaled from the TOML
config file could not be re-marshaled to TOML correctly.

Fixes #31183
2025-02-17 09:47:12 +01:00
Felix Lange e5bc789185
consensus/beacon: fix isPostMerge for mainnet (#31191)
This fixes a regression introduced in #31153 where we didn't consider
mainnet to be in PoS, causing #31190.
The problem is, `params.MainnetChainConfig` does not have a defined
`MergeNetsplitBlock`, so it isn't considered to be in PoS in
`CalcDifficulty`.
2025-02-17 07:30:06 +01:00
minh-bq 68de26e346
core/types: create block's bloom by merging receipts' bloom (#31129)
Currently, when calculating block's bloom, we loop through all the
receipt logs to calculate the hash value. However, normally, after going
through applyTransaction, the receipt's bloom is already calculated
based on the receipt log, so the block's bloom can be calculated by just
ORing these receipt's blooms.
```
goos: darwin
goarch: arm64
pkg: github.com/ethereum/go-ethereum/core/types
cpu: Apple M1 Pro
BenchmarkCreateBloom
BenchmarkCreateBloom/small
BenchmarkCreateBloom/small-10             810922              1481 ns/op             104 B/op          5 allocs/op
BenchmarkCreateBloom/large
BenchmarkCreateBloom/large-10               8173            143764 ns/op            9614 B/op        401 allocs/op
BenchmarkCreateBloom/small-mergebloom
BenchmarkCreateBloom/small-mergebloom-10                 5178918               232.0 ns/op             0 B/op          0 allocs/op
BenchmarkCreateBloom/large-mergebloom
BenchmarkCreateBloom/large-mergebloom-10                   54110             22207 ns/op               0 B/op          0 allocs/op
```

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
Co-authored-by: Zsolt Felfoldi <zsfelfoldi@gmail.com>
2025-02-13 18:05:58 +01:00
Felix Lange 77762820c9 version: begin v1.15.2 release cycle 2025-02-13 16:26:36 +01:00
Felix Lange b027a90ac0 version: release go-ethereum v1.15.1 stable 2025-02-13 16:21:36 +01:00
rjl493456442 913fee4be9
core/rawdb: skip setting flushOffset in read-only mode (#31173)
This PR addresses a flaw in the freezer table upgrade path.

In v1.15.0, freezer table v2 was introduced, including an additional 
field (`flushOffset`) maintained in the metadata file. To ensure 
backward compatibility, an upgrade path was implemented for legacy
freezer tables by setting `flushOffset` to the size of the index file.

However, if the freezer table is opened in read-only mode, this file 
write operation is rejected, causing Geth to shut down entirely.

Given that invalid items in the freezer index file can be detected and 
truncated, all items in freezer v0 index files are guaranteed to be
complete. Therefore, when operating in read-only mode, it is safe to
use the  freezer data without performing an upgrade.
2025-02-13 14:48:03 +01:00
Felix Lange 8ec4a06b3f
core: sanity-check fork configuration in genesis (#31171)
This is to prevent a crash on startup with a custom genesis configuration.
With this change in place, upgrading a chain created by geth v1.14.x and
below will now print an error instead of crashing:

    Fatal: Failed to register the Ethereum service: invalid chain configuration: missing entry for fork "cancun" in blobSchedule

Arguably this is not great, and it should just auto-upgrade the config.
We'll address this in a follow-up PR for geth v1.15.2
2025-02-13 13:05:05 +01:00
45 changed files with 496 additions and 408 deletions

View File

@ -23,7 +23,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: 1.23.0 go-version: 1.24.0
cache: false cache: false
- name: Run linters - name: Run linters
@ -39,7 +39,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: 1.23.0 go-version: 1.24.0
cache: false cache: false
- name: Run tests - name: Run tests
run: go test -short ./... run: go test -short ./...

View File

@ -15,7 +15,7 @@ jobs:
os: linux os: linux
arch: amd64 arch: amd64
dist: focal dist: focal
go: 1.23.x go: 1.24.x
env: env:
- docker - docker
services: services:
@ -33,7 +33,7 @@ jobs:
os: linux os: linux
dist: focal dist: focal
sudo: required sudo: required
go: 1.23.x go: 1.24.x
env: env:
- azure-linux - azure-linux
git: git:
@ -85,7 +85,7 @@ jobs:
os: linux os: linux
arch: amd64 arch: amd64
dist: focal dist: focal
go: 1.23.x go: 1.24.x
script: script:
- travis_wait 45 go run build/ci.go test $TEST_PACKAGES - travis_wait 45 go run build/ci.go test $TEST_PACKAGES
@ -93,7 +93,7 @@ jobs:
if: type = push if: type = push
os: linux os: linux
dist: focal dist: focal
go: 1.22.x go: 1.23.x
script: script:
- travis_wait 45 go run build/ci.go test $TEST_PACKAGES - travis_wait 45 go run build/ci.go test $TEST_PACKAGES
@ -102,7 +102,7 @@ jobs:
if: type = cron || (type = push && tag ~= /^v[0-9]/) if: type = cron || (type = push && tag ~= /^v[0-9]/)
os: linux os: linux
dist: focal dist: focal
go: 1.23.x go: 1.24.x
env: env:
- ubuntu-ppa - ubuntu-ppa
git: git:
@ -118,7 +118,7 @@ jobs:
if: type = cron if: type = cron
os: linux os: linux
dist: focal dist: focal
go: 1.23.x go: 1.24.x
env: env:
- azure-purge - azure-purge
git: git:
@ -131,7 +131,7 @@ jobs:
if: type = cron if: type = cron
os: linux os: linux
dist: focal dist: focal
go: 1.23.x go: 1.24.x
env: env:
- racetests - racetests
script: script:

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.23-alpine AS builder FROM golang:1.24-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.23-alpine AS builder FROM golang:1.24-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

@ -5,82 +5,109 @@
# https://github.com/ethereum/execution-spec-tests/releases/download/pectra-devnet-6%40v1.0.0/fixtures_pectra-devnet-6.tar.gz # https://github.com/ethereum/execution-spec-tests/releases/download/pectra-devnet-6%40v1.0.0/fixtures_pectra-devnet-6.tar.gz
b69211752a3029083c020dc635fe12156ca1a6725a08559da540a0337586a77e fixtures_pectra-devnet-6.tar.gz b69211752a3029083c020dc635fe12156ca1a6725a08559da540a0337586a77e fixtures_pectra-devnet-6.tar.gz
# version:golang 1.23.6 # version:golang 1.24.0
# https://go.dev/dl/ # https://go.dev/dl/
039c5b04e65279daceee8a6f71e70bd05cf5b801782b6f77c6e19e2ed0511222 go1.23.6.src.tar.gz d14120614acb29d12bcab72bd689f257eb4be9e0b6f88a8fb7e41ac65f8556e5 go1.24.0.src.tar.gz
adec10f4ba56591f523aa04851f7f6900b1c61508dfa6b80e62717a8e6684a5c go1.23.6.aix-ppc64.tar.gz 5d04588154d5923bd8e26b76111806340ec55c41af1b05623ea744fcb3d6bc22 go1.24.0.aix-ppc64.tar.gz
782da50ce8ec5e98fac2cd3cdc6a1d7130d093294fc310038f651444232a3fb0 go1.23.6.darwin-amd64.tar.gz 7af054e5088b68c24b3d6e135e5ca8d91bbd5a05cb7f7f0187367b3e6e9e05ee go1.24.0.darwin-amd64.tar.gz
5cae2450a1708aeb0333237a155640d5562abaf195defebc4306054565536221 go1.23.6.darwin-arm64.tar.gz dee0ea64411a00b47ded586d5a8e30cfe3acf51564aa1bb24e039a6dca807a29 go1.24.0.darwin-amd64.pkg
d52efb3020d9332477ade98163c03d2f2fe3e051b0e7e01f0e167412c66de0cb go1.23.6.dragonfly-amd64.tar.gz fd9cfb5dd6c75a347cfc641a253f0db1cebaca16b0dd37965351c6184ba595e4 go1.24.0.darwin-arm64.tar.gz
d3287706b5823712ac6cf7dff684a556cff98163ef60e7b275abe3388c17aac7 go1.23.6.freebsd-386.tar.gz b19eb6b7ae87f8371c3e7a84d129db67779a2883d2fffa6bb90412b0167df133 go1.24.0.darwin-arm64.pkg
ebb4c6a9b0673dbdabc439877779ed6add16575e21bd0a7955c33f692789aef6 go1.23.6.freebsd-amd64.tar.gz d0dc34ad86aea746abe245994c68a9e1ad8f46ba8c4af901cd5861a4dd4c21df go1.24.0.dragonfly-amd64.tar.gz
b7241584afb0b161c09148f8fde16171bb743e47b99d451fbc5f5217ec7a88b6 go1.23.6.freebsd-arm.tar.gz 4ee02b1f3812aff4da79c79464ee4038ca61ad74b3a9619850f30435f81c2536 go1.24.0.freebsd-386.tar.gz
004718b53cedd7955d1b1dc4053539fcd1053c031f5f3374334a22befd1f8310 go1.23.6.freebsd-arm64.tar.gz 838191001f9324da904dece35a586a3156d548687db87ac9461aa3d38fc88b09 go1.24.0.freebsd-amd64.tar.gz
ca026ec8a30dd0c18164f40e1ce21bd725e2445f11699177d05815189a38de7a go1.23.6.freebsd-riscv64.tar.gz ce6ad4e84a40a8a1d848b7e31b0cddfd1cee8f7959e7dc358a8fa8b5566ea718 go1.24.0.freebsd-arm.tar.gz
7db973efa3fb2e48e45059b855721550fce8e90803e7373d3efd37b88dd821e8 go1.23.6.illumos-amd64.tar.gz 511f7b0cac4c4ed1066d324072ce223b906ad6b2a85f2e1c5d260eb7d08b5901 go1.24.0.freebsd-arm64.tar.gz
e61f87693169c0bbcc43363128f1e929b9dff0b7f448573f1bdd4e4a0b9687ba go1.23.6.linux-386.tar.gz a1e4072630dc589a2975ef51317b52c7d8599bf6f389fc59033c01e0a0fa705a go1.24.0.freebsd-riscv64.tar.gz
9379441ea310de000f33a4dc767bd966e72ab2826270e038e78b2c53c2e7802d go1.23.6.linux-amd64.tar.gz 7593e9dcee9f07c3df6d099f7d259f5734a6c0dccc5f28962f18e7f501c9bb21 go1.24.0.illumos-amd64.tar.gz
561c780e8f4a8955d32bf72e46af0b5ee5e0debe1e4633df9a03781878219202 go1.23.6.linux-arm64.tar.gz 90521453a59c6ce20364d2dc7c38532949b033b602ba12d782caeb90af1b0624 go1.24.0.linux-386.tar.gz
27a4611010c16b8c4f37ade3aada55bd5781998f02f348b164302fd5eea4eb74 go1.23.6.linux-armv6l.tar.gz dea9ca38a0b852a74e81c26134671af7c0fbe65d81b0dc1c5bfe22cf7d4c8858 go1.24.0.linux-amd64.tar.gz
c459226424372abc2b35957cc8955dad348330714f7605093325dbb73e33c750 go1.23.6.linux-loong64.tar.gz c3fa6d16ffa261091a5617145553c71d21435ce547e44cc6dfb7470865527cc7 go1.24.0.linux-arm64.tar.gz
e2a0aff70b958a3463a7d47132a2d0238369f64578d4f7f95e679e3a5af05622 go1.23.6.linux-mips.tar.gz 695dc54fa14cd3124fa6900d7b5ae39eeac23f7a4ecea81656070160fac2c54a go1.24.0.linux-armv6l.tar.gz
7d30ec7db056311d420bf930c16abcae13c0f41c26a202868f279721ec3c2f2f go1.23.6.linux-mips64.tar.gz a201e4c9b7e6d29ed64c43296ed88e81a66f82f2093ce45b766d2c526941396f go1.24.0.linux-loong64.tar.gz
74ca7bc475bcc084c6718b74df024d7de9612932cea8a6dc75e29d3a5315a23a go1.23.6.linux-mips64le.tar.gz f3ac039aae78ad0bfb08106406c2e62eaf763dd82ebaf0ecd539adadd1d729a6 go1.24.0.linux-mips.tar.gz
09bf935a14e9f59a20499989438b1655453480016bdbcb10406acf4df2678ccb go1.23.6.linux-mipsle.tar.gz f2e6456d45e024831b1da8d88b1bb6392cca9500c1b00841f525d76c9e9553e0 go1.24.0.linux-mips64.tar.gz
5cb2f6a5090276c72c5eda8a55896f5a3d6ea0f28d10fa1a50e8318640f02d6c go1.23.6.linux-ppc64.tar.gz b847893ff119389c939adc2b8516b6500204b7cb49d5e19b25e1c2091d2c74c6 go1.24.0.linux-mips64le.tar.gz
0f817201e83d78ddbfa27f5f78d9b72450b92cc21d5e045145efacd0d3244a99 go1.23.6.linux-ppc64le.tar.gz bd4aed27d02746c237c3921e97029ac6b6fe687a67436b8f52ff1f698d330bd9 go1.24.0.linux-mipsle.tar.gz
f95f7f817ab22ecab4503d0704d6449ea1aa26a595f57bf9b9f94ddf2aa7c1f3 go1.23.6.linux-riscv64.tar.gz 007123c9b06c41729a4bb3f166f4df7196adf4e33c2d2ab0e7e990175f0ce1d4 go1.24.0.linux-ppc64.tar.gz
321e7ed0d5416f731479c52fa7610b52b8079a8061967bd48cec6d66f671a60e go1.23.6.linux-s390x.tar.gz a871a43de7d26c91dd90cb6e0adacb214c9e35ee2188c617c91c08c017efe81a go1.24.0.linux-ppc64le.tar.gz
92d678fb8e1eeeb8c6af6f22e4e5494652dcbb4a320113fc08325cb9956a2d4c go1.23.6.netbsd-386.tar.gz 620dcf48c6297519aad6c81f8e344926dc0ab09a2a79f1e306964aece95a553d go1.24.0.linux-riscv64.tar.gz
86ba51e7bb26b30ea6a8d88ddb79d8e8c83b4116200040ecb7a5a44cf90a8c5c go1.23.6.netbsd-amd64.tar.gz 544d78b077c6b54bf78958c4a8285abec2d21f668fb007261c77418cd2edbb46 go1.24.0.linux-s390x.tar.gz
4b974c35345100f0be6ea66afab2781de91ee9882117314126eaf0ae90fd3816 go1.23.6.netbsd-arm.tar.gz 8b143a7edefbaa2a0b0246c9df2df1bac9fbed909d8615a375c08da7744e697d go1.24.0.netbsd-386.tar.gz
53e3589fc38e787a493ea038961f8e40803714dbb42754c1713b00099c12e9b9 go1.23.6.netbsd-arm64.tar.gz 67150a6dd7bdb9c4e88d77f46ee8c4dc99d5e71deca4912d8c2c85f7a16d0262 go1.24.0.netbsd-amd64.tar.gz
6d2317b3a8505ccebff8f72d943f2ac9b82c115632e54a53a786eff24ced56d9 go1.23.6.openbsd-386.tar.gz 446b2539f11218fd6f6f6e3dd90b20ae55a06afe129885eeb3df51eb344eb0f6 go1.24.0.netbsd-arm.tar.gz
f699e707d95a984fcc00361d91aecdb413d3c75e18235156ffba7a89edf68aae go1.23.6.openbsd-amd64.tar.gz 370115b6ff7d30b29431223de348eb11ab65e3c92627532d97fd55f63f94e7a8 go1.24.0.netbsd-arm64.tar.gz
3c1cf6ab893657d0bf1942e40ce115acfd27cbce1ccb9bc88fd9cd21ca3d489f go1.23.6.openbsd-arm.tar.gz cbda5f15f06ed9630f122a53542d9de13d149643633c74f1dcb45e79649b788a go1.24.0.openbsd-386.tar.gz
cc0875535d14001f2da23ae9af89025b28c466e8f4f4c63f991ebb6f4b02f66c go1.23.6.openbsd-arm64.tar.gz 926f601d0e655ab1e8d7f357fd82542e5cf206c38c4e2f9fccf0706987d38836 go1.24.0.openbsd-amd64.tar.gz
64de80e29ca66cb566cbf8be030bf8599953af4e48402eab724cbe0a08b40602 go1.23.6.openbsd-ppc64.tar.gz 8a54892f8c933c541fff144a825d0fdc41bae14b0832aab703cb75eb4cb64f2c go1.24.0.openbsd-arm.tar.gz
c398a6b43c569f34bb4a2d16b52f8010eaac9a2a82ecac0602b4338e35cef377 go1.23.6.openbsd-riscv64.tar.gz ef7fddcef0a22c7900c178b7687cf5aa25c2a9d46a3cc330b77a6de6e6c2396b go1.24.0.openbsd-arm64.tar.gz
10998b6b130bb7b542b407f0db42b86a913b111f8fa86d44394beaace4d45f01 go1.23.6.plan9-386.tar.gz b3b5e2e2b53489ded2c2c21900ddcbbdb7991632bb5b42f05f125d71675e0b76 go1.24.0.openbsd-ppc64.tar.gz
9fbe8065436d8d12c02f19f64f51c9107da3a7a4ac46ab5777e182e9fe88c32f go1.23.6.plan9-amd64.tar.gz fbcb1dbf1269b4079dc4fd0b15f3274b9d635f1a7e319c3fc1a907b03280348e go1.24.0.openbsd-riscv64.tar.gz
8e3c826b884daee2de37e3b070d7eac4cea5d68edab8db09910e22201c75db83 go1.23.6.plan9-arm.tar.gz 33b4221e1c174a16e3f661deab6c60838ac4ae6cb869a4da1d1115773ceed88b go1.24.0.plan9-386.tar.gz
b619eff63fec86daaea92ca170559e448a58b8ba0b92eef1971bc14e92ea86a7 go1.23.6.solaris-amd64.tar.gz 111a89014019cdbd69c2978de9b3e201f77e35183c8ab3606fba339d38f28549 go1.24.0.plan9-amd64.tar.gz
96820c0f5d464dd694543329e9b4d413b17c821c03a055717a29e6735b44c2d8 go1.23.6.windows-386.zip 8da3d3997049f40ebe0cd336a9bb9e4bfa4832df3c90a32f07383371d6d74849 go1.24.0.plan9-arm.tar.gz
53fec1586850b2cf5ad6438341ff7adc5f6700dd3ec1cfa3f5e8b141df190243 go1.23.6.windows-amd64.zip b6069da21dc95ccdbd047675b584e5480ffc3eba35f9e7c8b0e7b317aaf01e2c go1.24.0.solaris-amd64.tar.gz
22c2518c45c20018afa20d5376dc9fd7a7e74367240ed7b5209e79a30b5c4218 go1.23.6.windows-arm.zip b53c28a4c2863ec50ab4a1dbebe818ef6177f86773b6f43475d40a5d9aa4ec9e go1.24.0.windows-386.zip
a2d2ec1b3759552bdd9cdf58858f91dfbfd6ab3a472f00b5255acbed30b1aa41 go1.23.6.windows-arm64.zip f07677013cd7861c5e16067b0a82144c23c4bf72c139c762e142440f4c926f61 go1.24.0.windows-386.msi
96b7280979205813759ee6947be7e3bb497da85c482711116c00522e3bb41ff1 go1.24.0.windows-amd64.zip
4e78016d889431eb16aa0f87868cf52479b90059791c94a4ff45872d0573089e go1.24.0.windows-amd64.msi
53f73450fb66075d16be9f206e9177bd972b528168271918c4747903b5596c3d go1.24.0.windows-arm64.zip
4f9780158fb7996dcbcbc7c7ef208f880b5e8c1f2792ba3ede0c75050c1bc23a go1.24.0.windows-arm64.msi
# version:golangci 1.63.4 # version:golangci 1.64.4
# https://github.com/golangci/golangci-lint/releases/ # https://github.com/golangci/golangci-lint/releases/
# https://github.com/golangci/golangci-lint/releases/download/v1.63.4/ # https://github.com/golangci/golangci-lint/releases/download/v1.64.4/
878d017cc360e4fb19510d39852c8189852e3c48e7ce0337577df73507c97d68 golangci-lint-1.63.4-darwin-amd64.tar.gz f31ef6e20c62acc31eb7b851d611b4bd10256d1b1d8be38f0cceec300b5b60db golangci-lint-1.64.4-darwin-amd64.tar.gz
a2b630c2ac8466393f0ccbbede4462387b6c190697a70bc2298c6d2123f21bbf golangci-lint-1.63.4-darwin-arm64.tar.gz bb4a9ece7ef66ef49bd6de873f5f5ec801cf93dacf58efb360cc939b4fd37c47 golangci-lint-1.64.4-darwin-arm64.tar.gz
8938b74aa92888e561a1c5a4c175110b92f84e7d24733703e6d9ebc39e9cd5f8 golangci-lint-1.63.4-freebsd-386.tar.gz fd8f9046150356e36ad8af31f99219515d5e0ff6e8e9f4204182312447018fcf golangci-lint-1.64.4-freebsd-386.tar.gz
054903339d620df2e760b978920100986e3b03bcb058f669d520a71dac9c34ed golangci-lint-1.63.4-freebsd-amd64.tar.gz bbae940caa31cb1d2d8d26abd867666cd92746d2ddc63d6917d128c456d715ef golangci-lint-1.64.4-freebsd-amd64.tar.gz
a19d499f961a02608348e8b626537a88edfaab6e1b6534f1eff742b5d6d750e4 golangci-lint-1.63.4-freebsd-armv6.tar.gz 86eb00cbdc5e277857a380d556d78a42b3edf8aae5991de8767dce7da337d73b golangci-lint-1.64.4-freebsd-armv6.tar.gz
00d616f0fb275b780ce4d26604bdd7fdbfe6bc9c63acd5a0b31498e1f7511108 golangci-lint-1.63.4-freebsd-armv7.tar.gz c0f7d50f4fcd39ae8bda181c127b078a79d87c885ac472c4cce5b01134dde5bc golangci-lint-1.64.4-freebsd-armv7.tar.gz
d453688e0eabded3c1a97ff5a2777bb0df5a18851efdaaaf6b472e3e5713c33e golangci-lint-1.63.4-illumos-amd64.tar.gz 31d264fa26a73a583425bc9b39c18de70a330e346fe800e80c277ddb5f8477b6 golangci-lint-1.64.4-illumos-amd64.tar.gz
6b1bec847fc9f347d53712d05606a49d55d0e3b5c1bacadfed2393f3503de0e9 golangci-lint-1.63.4-linux-386.tar.gz 3dccc18a6b1a0f2518196190ed56277b1480b381231605936eca6b862426b83c golangci-lint-1.64.4-linux-386.deb
01abb14a4df47b5ca585eff3c34b105023cba92ec34ff17212dbb83855581690 golangci-lint-1.63.4-linux-amd64.tar.gz b95f3e757c59ada75144bd086478ab63bcda83c2b2a935e60d8f39aff20fbcd2 golangci-lint-1.64.4-linux-386.rpm
51f0c79d19a92353e0465fb30a4901a0644a975d34e6f399ad2eebc0160bbb24 golangci-lint-1.63.4-linux-arm64.tar.gz 8fa58af0022ae0487162c02d08075e2d869c9b5f8613a64b85fd769a2a2d2b93 golangci-lint-1.64.4-linux-386.tar.gz
8d0a43f41e8424fbae10f7aa2dc29999f98112817c6dba63d7dc76832940a673 golangci-lint-1.63.4-linux-armv6.tar.gz fa80d2ad920fc74b85a0b93ad1671fd27c9c4d6f22e167cc4e1da758d72dd893 golangci-lint-1.64.4-linux-amd64.deb
1045a047b31e9302c9160c7b0f199f4ac1bd02a1b221a2d9521bd3507f0cf671 golangci-lint-1.63.4-linux-armv7.tar.gz 8bf2e3c82504a893a12e84ecbc8071f787075d2fdc1ef946deda3d29aae1afad golangci-lint-1.64.4-linux-amd64.rpm
933fe10ab50ce3bb0806e15a4ae69fe20f0549abf91dea0161236000ca706e67 golangci-lint-1.63.4-linux-loong64.tar.gz 7de8f80a12cd3052610e6be21f08f2220805b1f3e43b3b6ec843f14a12140de2 golangci-lint-1.64.4-linux-amd64.tar.gz
45798630cbad5642862766051199fa862ef3c33d569cab12f01cac4f68e2ddd5 golangci-lint-1.63.4-linux-mips64.tar.gz ade222b9ae997a2875e44ed53ca5a129f24944b232132d0a5898f101381d3bfa golangci-lint-1.64.4-linux-arm64.deb
86ae25335ddb24975d2c915c1af0c7fad70dce99d0b4614fa4bee392de714aa2 golangci-lint-1.63.4-linux-mips64le.tar.gz 8f9f8617ed0d8b8f62c8dfe69877932c0d85f0d83a9ec3250b04777c7133ada1 golangci-lint-1.64.4-linux-arm64.rpm
33dabd11aaba4b602938da98bcf49aabab55019557e0115cdc3dbcc3009768fa golangci-lint-1.63.4-linux-ppc64le.tar.gz debf1f73e71f1dd288957574eab4e7515b1b04c4ac2f127192181da8a42f0e8e golangci-lint-1.64.4-linux-arm64.tar.gz
4e7a81230a663bcdf30bba5689ce96040abc76994dbc2003dce32c8dca8c06f3 golangci-lint-1.63.4-linux-riscv64.tar.gz 3f616caa4a16738114ad29076a333c62bb0650fe4846b438c341d235f78ee5aa golangci-lint-1.64.4-linux-armv6.deb
21370b49c7c47f4d9b8f982c952f940b01e65710174c3b4dad7b6452d58f92ec golangci-lint-1.63.4-linux-s390x.tar.gz 6a7c9d7b7c57d7d440e1e3f133e18e4b5b703604d4ae7f7862fb9ea461887a8b golangci-lint-1.64.4-linux-armv6.rpm
255866a6464c7e11bb7edd8e6e6ad54f11e1f01b82ba9ca229698ac788cd9724 golangci-lint-1.63.4-netbsd-386.tar.gz d7b9e3c89af93d98c6b5a555ef48e25bee24f84d7825a29e343e9966404d5b4d golangci-lint-1.64.4-linux-armv6.tar.gz
2798c040ac658bda97224f204795199c81ac97bb207b21c02b664aaed380d5d2 golangci-lint-1.63.4-netbsd-amd64.tar.gz 18179ecf04ace3051450852424b31a4d26644a3912e759cd595e624eee0174bd golangci-lint-1.64.4-linux-armv7.deb
b910eecffd0064103837e7e1abe870deb8ade22331e6dffe319f430d49399c8e golangci-lint-1.63.4-netbsd-arm64.tar.gz f669fce85d3edc3d557d1e64e2241d895f1ee676f79d139874bf76693cc447a2 golangci-lint-1.64.4-linux-armv7.rpm
df2693ef37147b457c3e2089614537dd2ae2e18e53641e756a5b404f4c72d3fa golangci-lint-1.63.4-netbsd-armv6.tar.gz 9bbaa13b474ecb1560fb05aee0a8cab3e9cc327d41632bee8b553b766f2bf756 golangci-lint-1.64.4-linux-armv7.tar.gz
a28a533366974bd7834c4516cd6075bff3419a508d1ed7aa63ae8182768b352e golangci-lint-1.63.4-netbsd-armv7.tar.gz b5a2725adba2a1b04a5160ffa0730ba30b88c1ee99ecbc65dd7075a8d70f3730 golangci-lint-1.64.4-linux-loong64.deb
368932775fb5c620b324dabf018155f3365f5e33c5af5b26e9321db373f96eea golangci-lint-1.63.4-windows-386.zip 28ac00afb3f6407808fe7c15a6002e5fe6b3b461df3fe0223603542e6f9b974a golangci-lint-1.64.4-linux-loong64.rpm
184d13c2b8f5441576bec2a0d8ba7b2d45445595cf796b879a73bcc98c39f8c1 golangci-lint-1.63.4-windows-amd64.zip 121170309fed82cb64d6fae5020ef2b194e591a53156370c221a80121cc4aa08 golangci-lint-1.64.4-linux-loong64.tar.gz
4fabf175d5b05ef0858ded49527948eebac50e9093814979fd84555a75fb80a6 golangci-lint-1.63.4-windows-arm64.zip aadfaab41380f53ada8f7ad4fa9af784bb882eaaa1e3939e048b3a5ea8f2c13f golangci-lint-1.64.4-linux-mips64.deb
e92be3f3ff30d4a849fb4b9a4c8d56837dee45269cb405a3ecad52fa034c781b golangci-lint-1.63.4-windows-armv6.zip 6fecbff69086e316dd028050d3ebf82fc466c7f4dc0f6084307054621101c202 golangci-lint-1.64.4-linux-mips64.rpm
c71d348653b8f7fbb109bb10c1a481722bc6b0b2b6e731b897f99ac869f7653e golangci-lint-1.63.4-windows-armv7.zip 430c48034527af028dc608c115166f47b6b67c8cb83a317d9d44876b9753292a golangci-lint-1.64.4-linux-mips64.tar.gz
432126af2bbbd639dbbcc2c265337f104cc613a7b4c5a8fb5e49f182b428f077 golangci-lint-1.64.4-linux-mips64le.deb
cfa663eee0fae721510d6dc31e61db4be51b4e4244eb7de2b6a9bc6d475551e5 golangci-lint-1.64.4-linux-mips64le.rpm
2bacfac65182893c5ceb67b61d5b9d2b24da47726d84cb87d734a6e32f040148 golangci-lint-1.64.4-linux-mips64le.tar.gz
66d86e47d68420c03045eff0698e9acf9f82d97cd1f07d7e52837a6e544eceed golangci-lint-1.64.4-linux-ppc64le.deb
05466bd2d8e82f7245b838e29d0c90cdbaf67375b2b5bc980d8510d5edb206ad golangci-lint-1.64.4-linux-ppc64le.rpm
e013b6980f7140712af0aedc9a661265e1d3c6adc7e9d045734e3686a3601acc golangci-lint-1.64.4-linux-ppc64le.tar.gz
753980d2fb421d35292b71b51f9bb0552f18de2eb181ccf692ef79e086ad2304 golangci-lint-1.64.4-linux-riscv64.deb
73a33a883020298f8c652a4ace4f6888103d80d411fe3e9b77ce0a3b36ff7d3a golangci-lint-1.64.4-linux-riscv64.rpm
020efd09b894dc75012f43b1d4c58e69e5446ca3f79845b5e10a02588def3e1b golangci-lint-1.64.4-linux-riscv64.tar.gz
4d99a16bc9ff5cea5e4ae3568c6254390fbdad8f1d370c287744409112bceff9 golangci-lint-1.64.4-linux-s390x.deb
6e63374a9f95fc09f2bb9501059eb18b8107e08416722ba7b561ae385d80b33b golangci-lint-1.64.4-linux-s390x.rpm
62a6febb892b26eee84a32cc99d04afe90bf62d0970774b1bab75e36b66f53b4 golangci-lint-1.64.4-linux-s390x.tar.gz
5ba4d235f9abd60d2d280f9fe4228c6ddab11ae9fe48d253b7e477046675f1f6 golangci-lint-1.64.4-netbsd-386.tar.gz
061643bb4370a52010e5e76f88f5b5220e51058df50af86b45286263af92b321 golangci-lint-1.64.4-netbsd-amd64.tar.gz
12b2be6c35bcf7a36374e952c7efec7905a17fa3ebe6214924ba8721b766c4af golangci-lint-1.64.4-netbsd-arm64.tar.gz
553a71a677751dccee082ed8afe24cf58bef725f72aa02aedcc6758dd8f44125 golangci-lint-1.64.4-netbsd-armv6.tar.gz
74a5a5a7b8c8cd11dccdec303ee6592d904b09836782e6d658be359737f300ef golangci-lint-1.64.4-netbsd-armv7.tar.gz
b3ceea2187843f9ba6510303141a72465621e3f190a262c0b48707b9e983ea9a golangci-lint-1.64.4-source.tar.gz
fda4de312fcb0b4853b03bcdfb31ac631a68fa0b966f6aa010eb30d14427180b golangci-lint-1.64.4-windows-386.zip
8fc60bd809f86c6431ed8f3d1f25917538c0ebc93e670cfb199f25bbaa56e602 golangci-lint-1.64.4-windows-amd64.zip
b9058c9d2ae8d75048c6ad8885d11e5ac0a6c40be2af85bfa6605e48d69d3eb6 golangci-lint-1.64.4-windows-arm64.zip
809b0131adb1aa8b359becd13222df367b505bc2955bb3b1d2d0dd6f07347b13 golangci-lint-1.64.4-windows-armv6.zip
fc43f8c95d6bec8ba9a3557a0bb63cf9f504137ce6d24cfdc4c330d46f7779d2 golangci-lint-1.64.4-windows-armv7.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

@ -304,7 +304,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
// Set the receipt logs and create the bloom filter. // Set the receipt logs and create the bloom filter.
receipt.Logs = statedb.GetLogs(tx.Hash(), vmContext.BlockNumber.Uint64(), blockHash) receipt.Logs = statedb.GetLogs(tx.Hash(), vmContext.BlockNumber.Uint64(), blockHash)
receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) receipt.Bloom = types.CreateBloom(receipt)
// These three are non-consensus fields: // These three are non-consensus fields:
//receipt.BlockHash //receipt.BlockHash
//receipt.BlockNumber //receipt.BlockNumber
@ -376,7 +377,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
StateRoot: root, StateRoot: root,
TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)), TxRoot: types.DeriveSha(includedTxs, trie.NewStackTrie(nil)),
ReceiptRoot: types.DeriveSha(receipts, trie.NewStackTrie(nil)), ReceiptRoot: types.DeriveSha(receipts, trie.NewStackTrie(nil)),
Bloom: types.CreateBloom(receipts), Bloom: types.MergeBloom(receipts),
LogsHash: rlpHash(statedb.Logs()), LogsHash: rlpHash(statedb.Logs()),
Receipts: receipts, Receipts: receipts,
Rejected: rejectedTxs, Rejected: rejectedTxs,

View File

@ -262,7 +262,7 @@ var (
} }
StateHistoryFlag = &cli.Uint64Flag{ StateHistoryFlag = &cli.Uint64Flag{
Name: "history.state", Name: "history.state",
Usage: "Number of recent blocks to retain state history for (default = 90,000 blocks, 0 = entire chain)", Usage: "Number of recent blocks to retain state history for, only relevant in state.scheme=path (default = 90,000 blocks, 0 = entire chain)",
Value: ethconfig.Defaults.StateHistory, Value: ethconfig.Defaults.StateHistory,
Category: flags.StateCategory, Category: flags.StateCategory,
} }

View File

@ -75,9 +75,11 @@ func New(ethone consensus.Engine) *Beacon {
// isPostMerge reports whether the given block number is assumed to be post-merge. // isPostMerge reports whether the given block number is assumed to be post-merge.
// Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or // Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or
// PoA chain for unit testing purposes. // PoA chain for unit testing purposes.
func isPostMerge(config *params.ChainConfig, block uint64) bool { func isPostMerge(config *params.ChainConfig, blockNum uint64, timestamp uint64) bool {
mergedAtGenesis := config.TerminalTotalDifficulty != nil && config.TerminalTotalDifficulty.Sign() == 0 mergedAtGenesis := config.TerminalTotalDifficulty != nil && config.TerminalTotalDifficulty.Sign() == 0
return mergedAtGenesis || config.MergeNetsplitBlock != nil && block >= config.MergeNetsplitBlock.Uint64() return mergedAtGenesis ||
config.MergeNetsplitBlock != nil && blockNum >= config.MergeNetsplitBlock.Uint64() ||
config.ShanghaiTime != nil && timestamp >= *config.ShanghaiTime
} }
// Author implements consensus.Engine, returning the verified author of the block. // Author implements consensus.Engine, returning the verified author of the block.
@ -327,7 +329,7 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [
// Prepare implements consensus.Engine, initializing the difficulty field of a // Prepare implements consensus.Engine, initializing the difficulty field of a
// header to conform to the beacon protocol. The changes are done inline. // header to conform to the beacon protocol. The changes are done inline.
func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
if !isPostMerge(chain.Config(), header.Number.Uint64()) { if !isPostMerge(chain.Config(), header.Number.Uint64(), header.Time) {
return beacon.ethone.Prepare(chain, header) return beacon.ethone.Prepare(chain, header)
} }
header.Difficulty = beaconDifficulty header.Difficulty = beaconDifficulty
@ -437,7 +439,7 @@ func (beacon *Beacon) SealHash(header *types.Header) common.Hash {
// the difficulty that a new block should have when created at time // the difficulty that a new block should have when created at time
// given the parent block's time and difficulty. // given the parent block's time and difficulty.
func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
if !isPostMerge(chain.Config(), parent.Number.Uint64()+1) { if !isPostMerge(chain.Config(), parent.Number.Uint64()+1, time) {
return beacon.ethone.CalcDifficulty(chain, time, parent) return beacon.ethone.CalcDifficulty(chain, time, parent)
} }
return beaconDifficulty return beaconDifficulty

View File

@ -83,6 +83,8 @@ func CalcExcessBlobGas(config *params.ChainConfig, parent *types.Header, headTim
func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int { func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int {
var frac uint64 var frac uint64
switch config.LatestFork(header.Time) { switch config.LatestFork(header.Time) {
case forks.Osaka:
frac = config.BlobScheduleConfig.Osaka.UpdateFraction
case forks.Prague: case forks.Prague:
frac = config.BlobScheduleConfig.Prague.UpdateFraction frac = config.BlobScheduleConfig.Prague.UpdateFraction
case forks.Cancun: case forks.Cancun:
@ -103,6 +105,8 @@ func MaxBlobsPerBlock(cfg *params.ChainConfig, time uint64) int {
s = cfg.BlobScheduleConfig s = cfg.BlobScheduleConfig
) )
switch { switch {
case cfg.IsOsaka(london, time) && s.Osaka != nil:
return s.Osaka.Max
case cfg.IsPrague(london, time) && s.Prague != nil: case cfg.IsPrague(london, time) && s.Prague != nil:
return s.Prague.Max return s.Prague.Max
case cfg.IsCancun(london, time) && s.Cancun != nil: case cfg.IsCancun(london, time) && s.Cancun != nil:
@ -125,6 +129,8 @@ func LatestMaxBlobsPerBlock(cfg *params.ChainConfig) int {
return 0 return 0
} }
switch { switch {
case s.Osaka != nil:
return s.Osaka.Max
case s.Prague != nil: case s.Prague != nil:
return s.Prague.Max return s.Prague.Max
case s.Cancun != nil: case s.Cancun != nil:
@ -144,6 +150,8 @@ func targetBlobsPerBlock(cfg *params.ChainConfig, time uint64) int {
s = cfg.BlobScheduleConfig s = cfg.BlobScheduleConfig
) )
switch { switch {
case cfg.IsOsaka(london, time) && s.Osaka != nil:
return s.Osaka.Target
case cfg.IsPrague(london, time) && s.Prague != nil: case cfg.IsPrague(london, time) && s.Prague != nil:
return s.Prague.Target return s.Prague.Target
case cfg.IsCancun(london, time) && s.Cancun != nil: case cfg.IsCancun(london, time) && s.Cancun != nil:

View File

@ -129,7 +129,11 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
} }
// Validate the received block's bloom with the one derived from the generated receipts. // Validate the received block's bloom with the one derived from the generated receipts.
// For valid blocks this should always validate to true. // For valid blocks this should always validate to true.
rbloom := types.CreateBloom(res.Receipts) //
// Receipts must go through MakeReceipt to calculate the receipt's bloom
// already. Merge the receipt's bloom together instead of recalculating
// everything.
rbloom := types.MergeBloom(res.Receipts)
if rbloom != header.Bloom { if rbloom != header.Bloom {
return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom) return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom)
} }

View File

@ -364,6 +364,11 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
} }
newCfg := genesis.chainConfigOrDefault(ghash, storedCfg) newCfg := genesis.chainConfigOrDefault(ghash, storedCfg)
// Sanity-check the new configuration.
if err := newCfg.CheckConfigForkOrder(); err != nil {
return nil, common.Hash{}, nil, err
}
// TODO(rjl493456442) better to define the comparator of chain config // TODO(rjl493456442) better to define the comparator of chain config
// and short circuit if the chain config is not changed. // and short circuit if the chain config is not changed.
compatErr := storedCfg.CheckCompatible(newCfg, head.Number.Uint64(), head.Time) compatErr := storedCfg.CheckCompatible(newCfg, head.Number.Uint64(), head.Time)

View File

@ -281,6 +281,7 @@ func TestVerkleGenesisCommit(t *testing.T) {
BlobScheduleConfig: &params.BlobScheduleConfig{ BlobScheduleConfig: &params.BlobScheduleConfig{
Cancun: params.DefaultCancunBlobConfig, Cancun: params.DefaultCancunBlobConfig,
Prague: params.DefaultPragueBlobConfig, Prague: params.DefaultPragueBlobConfig,
Osaka: params.DefaultOsakaBlobConfig,
Verkle: params.DefaultPragueBlobConfig, Verkle: params.DefaultPragueBlobConfig,
}, },
} }

View File

@ -338,7 +338,7 @@ func TestBlockReceiptStorage(t *testing.T) {
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
GasUsed: 111111, GasUsed: 111111,
} }
receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) receipt1.Bloom = types.CreateBloom(receipt1)
receipt2 := &types.Receipt{ receipt2 := &types.Receipt{
PostState: common.Hash{2}.Bytes(), PostState: common.Hash{2}.Bytes(),
@ -351,7 +351,7 @@ func TestBlockReceiptStorage(t *testing.T) {
ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
GasUsed: 222222, GasUsed: 222222,
} }
receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) receipt2.Bloom = types.CreateBloom(receipt2)
receipts := []*types.Receipt{receipt1, receipt2} receipts := []*types.Receipt{receipt1, receipt2}
// Check that no receipt entries are in a pristine database // Check that no receipt entries are in a pristine database
@ -679,7 +679,7 @@ func TestReadLogs(t *testing.T) {
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
GasUsed: 111111, GasUsed: 111111,
} }
receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1}) receipt1.Bloom = types.CreateBloom(receipt1)
receipt2 := &types.Receipt{ receipt2 := &types.Receipt{
PostState: common.Hash{2}.Bytes(), PostState: common.Hash{2}.Bytes(),
@ -692,7 +692,7 @@ func TestReadLogs(t *testing.T) {
ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
GasUsed: 222222, GasUsed: 222222,
} }
receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) receipt2.Bloom = types.CreateBloom(receipt2)
receipts := []*types.Receipt{receipt1, receipt2} receipts := []*types.Receipt{receipt1, receipt2}
hash := common.BytesToHash([]byte{0x03, 0x14}) hash := common.BytesToHash([]byte{0x03, 0x14})

View File

@ -405,6 +405,13 @@ func (t *freezerTable) repairIndex() error {
// If legacy metadata is detected, attempt to recover the offset from the // If legacy metadata is detected, attempt to recover the offset from the
// index file to avoid clearing the entire table. // index file to avoid clearing the entire table.
if t.metadata.version == freezerTableV1 { if t.metadata.version == freezerTableV1 {
// Skip truncation if the legacy metadata is opened in read-only mode.
// Since all items in the legacy index file were forcibly synchronized,
// data integrity is guaranteed. Therefore, it's safe to leave any extra
// items untruncated in this special scenario.
if t.readonly {
return nil
}
t.logger.Info("Recovering freezer flushOffset for legacy table", "offset", size) t.logger.Info("Recovering freezer flushOffset for legacy table", "offset", size)
return t.metadata.setFlushOffset(size, true) return t.metadata.setFlushOffset(size, true)
} }

View File

@ -189,7 +189,7 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b
// Set the receipt logs and create the bloom filter. // Set the receipt logs and create the bloom filter.
receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash) receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash)
receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) receipt.Bloom = types.CreateBloom(receipt)
receipt.BlockHash = blockHash receipt.BlockHash = blockHash
receipt.BlockNumber = blockNumber receipt.BlockNumber = blockNumber
receipt.TransactionIndex = uint(statedb.TxIndex()) receipt.TransactionIndex = uint(statedb.TxIndex())
@ -229,7 +229,7 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
} }
evm.SetTxContext(NewEVMTxContext(msg)) evm.SetTxContext(NewEVMTxContext(msg))
evm.StateDB.AddAddressToAccessList(params.BeaconRootsAddress) evm.StateDB.AddAddressToAccessList(params.BeaconRootsAddress)
_, _, _ = evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) _, _, _ = evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
evm.StateDB.Finalise(true) evm.StateDB.Finalise(true)
} }
@ -253,7 +253,7 @@ func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
} }
evm.SetTxContext(NewEVMTxContext(msg)) evm.SetTxContext(NewEVMTxContext(msg))
evm.StateDB.AddAddressToAccessList(params.HistoryStorageAddress) evm.StateDB.AddAddressToAccessList(params.HistoryStorageAddress)
_, _, err := evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) _, _, err := evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -292,7 +292,7 @@ func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte
} }
evm.SetTxContext(NewEVMTxContext(msg)) evm.SetTxContext(NewEVMTxContext(msg))
evm.StateDB.AddAddressToAccessList(addr) evm.StateDB.AddAddressToAccessList(addr)
ret, _, _ := evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560) ret, _, _ := evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
evm.StateDB.Finalise(true) evm.StateDB.Finalise(true)
if len(ret) == 0 { if len(ret) == 0 {
return // skip empty output return // skip empty output

View File

@ -423,7 +423,6 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
var ( var (
msg = st.msg msg = st.msg
sender = vm.AccountRef(msg.From)
rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time) rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time)
contractCreation = msg.To == nil contractCreation = msg.To == nil
floorDataGas uint64 floorDataGas uint64
@ -484,7 +483,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
vmerr error // vm errors do not effect consensus and are therefore not assigned to err vmerr error // vm errors do not effect consensus and are therefore not assigned to err
) )
if contractCreation { if contractCreation {
ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value) ret, _, st.gasRemaining, vmerr = st.evm.Create(msg.From, msg.Data, st.gasRemaining, value)
} else { } else {
// Increment the nonce for the next transaction. // Increment the nonce for the next transaction.
st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1, tracing.NonceChangeEoACall) st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1, tracing.NonceChangeEoACall)
@ -507,7 +506,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
} }
// Execute the transaction's call. // Execute the transaction's call.
ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, value) ret, st.gasRemaining, vmerr = st.evm.Call(msg.From, st.to(), msg.Data, st.gasRemaining, value)
} }
// Compute refund counter, capped to a refund quotient. // Compute refund counter, capped to a refund quotient.

View File

@ -237,6 +237,9 @@ type extblock struct {
// //
// The body elements and the receipts are used to recompute and overwrite the // The body elements and the receipts are used to recompute and overwrite the
// relevant portions of the header. // relevant portions of the header.
//
// The receipt's bloom must already calculated for the block's bloom to be
// correctly calculated.
func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher) *Block { func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher) *Block {
if body == nil { if body == nil {
body = &Body{} body = &Body{}
@ -260,7 +263,10 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher TrieHasher
b.header.ReceiptHash = EmptyReceiptsHash b.header.ReceiptHash = EmptyReceiptsHash
} else { } else {
b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher) b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher)
b.header.Bloom = CreateBloom(receipts) // Receipts must go through MakeReceipt to calculate the receipt's bloom
// already. Merge the receipt's bloom together instead of recalculating
// everything.
b.header.Bloom = MergeBloom(receipts)
} }
if len(uncles) == 0 { if len(uncles) == 0 {

View File

@ -100,32 +100,35 @@ func (b *Bloom) UnmarshalText(input []byte) error {
return hexutil.UnmarshalFixedText("Bloom", input, b[:]) return hexutil.UnmarshalFixedText("Bloom", input, b[:])
} }
// CreateBloom creates a bloom filter out of the give Receipts (+Logs) // CreateBloom creates a bloom filter out of the give Receipt (+Logs)
func CreateBloom(receipts Receipts) Bloom { func CreateBloom(receipt *Receipt) Bloom {
buf := make([]byte, 6) var (
var bin Bloom bin Bloom
for _, receipt := range receipts { buf = make([]byte, 6)
for _, log := range receipt.Logs { )
bin.add(log.Address.Bytes(), buf) for _, log := range receipt.Logs {
for _, b := range log.Topics {
bin.add(b[:], buf)
}
}
}
return bin
}
// LogsBloom returns the bloom bytes for the given logs
func LogsBloom(logs []*Log) []byte {
buf := make([]byte, 6)
var bin Bloom
for _, log := range logs {
bin.add(log.Address.Bytes(), buf) bin.add(log.Address.Bytes(), buf)
for _, b := range log.Topics { for _, b := range log.Topics {
bin.add(b[:], buf) bin.add(b[:], buf)
} }
} }
return bin[:] return bin
}
// MergeBloom merges the precomputed bloom filters in the Receipts without
// recalculating them. It assumes that each receipts Bloom field is already
// correctly populated.
func MergeBloom(receipts Receipts) Bloom {
var bin Bloom
for _, receipt := range receipts {
if len(receipt.Logs) != 0 {
bl := receipt.Bloom.Bytes()
for i := range bin {
bin[i] |= bl[i]
}
}
}
return bin
} }
// Bloom9 returns the bloom filter for the given data // Bloom9 returns the bloom filter for the given data

View File

@ -126,26 +126,70 @@ func BenchmarkCreateBloom(b *testing.B) {
for i := 0; i < 200; i += 2 { for i := 0; i < 200; i += 2 {
copy(rLarge[i:], rSmall) copy(rLarge[i:], rSmall)
} }
b.Run("small", func(b *testing.B) { b.Run("small-createbloom", func(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
var bl Bloom
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
bl = CreateBloom(rSmall) for _, receipt := range rSmall {
receipt.Bloom = CreateBloom(receipt)
}
} }
b.StopTimer() b.StopTimer()
bl := MergeBloom(rSmall)
var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
got := crypto.Keccak256Hash(bl.Bytes()) got := crypto.Keccak256Hash(bl.Bytes())
if got != exp { if got != exp {
b.Errorf("Got %x, exp %x", got, exp) b.Errorf("Got %x, exp %x", got, exp)
} }
}) })
b.Run("large", func(b *testing.B) { b.Run("large-createbloom", func(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
var bl Bloom
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
bl = CreateBloom(rLarge) for _, receipt := range rLarge {
receipt.Bloom = CreateBloom(receipt)
}
} }
b.StopTimer() b.StopTimer()
bl := MergeBloom(rLarge)
var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
got := crypto.Keccak256Hash(bl.Bytes())
if got != exp {
b.Errorf("Got %x, exp %x", got, exp)
}
})
b.Run("small-mergebloom", func(b *testing.B) {
for _, receipt := range rSmall {
receipt.Bloom = CreateBloom(receipt)
}
b.ReportAllocs()
b.ResetTimer()
var bl Bloom
for i := 0; i < b.N; i++ {
bl = MergeBloom(rSmall)
}
b.StopTimer()
var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
got := crypto.Keccak256Hash(bl.Bytes())
if got != exp {
b.Errorf("Got %x, exp %x", got, exp)
}
})
b.Run("large-mergebloom", func(b *testing.B) {
for _, receipt := range rLarge {
receipt.Bloom = CreateBloom(receipt)
}
b.ReportAllocs()
b.ResetTimer()
var bl Bloom
for i := 0; i < b.N; i++ {
bl = MergeBloom(rLarge)
}
b.StopTimer()
var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949") var exp = common.HexToHash("c384c56ece49458a427c67b90fefe979ebf7104795be65dc398b280f24104949")
got := crypto.Keccak256Hash(bl.Bytes()) got := crypto.Keccak256Hash(bl.Bytes())
if got != exp { if got != exp {

View File

@ -291,7 +291,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
} }
r.CumulativeGasUsed = stored.CumulativeGasUsed r.CumulativeGasUsed = stored.CumulativeGasUsed
r.Logs = stored.Logs r.Logs = stored.Logs
r.Bloom = CreateBloom(Receipts{(*Receipt)(r)}) r.Bloom = CreateBloom((*Receipt)(r))
return nil return nil
} }

View File

@ -394,7 +394,7 @@ func TestTypedReceiptEncodingDecoding(t *testing.T) {
func TestReceiptMarshalBinary(t *testing.T) { func TestReceiptMarshalBinary(t *testing.T) {
// Legacy Receipt // Legacy Receipt
legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt}) legacyReceipt.Bloom = CreateBloom(legacyReceipt)
have, err := legacyReceipt.MarshalBinary() have, err := legacyReceipt.MarshalBinary()
if err != nil { if err != nil {
t.Fatalf("marshal binary error: %v", err) t.Fatalf("marshal binary error: %v", err)
@ -421,7 +421,7 @@ func TestReceiptMarshalBinary(t *testing.T) {
// 2930 Receipt // 2930 Receipt
buf.Reset() buf.Reset()
accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt}) accessListReceipt.Bloom = CreateBloom(accessListReceipt)
have, err = accessListReceipt.MarshalBinary() have, err = accessListReceipt.MarshalBinary()
if err != nil { if err != nil {
t.Fatalf("marshal binary error: %v", err) t.Fatalf("marshal binary error: %v", err)
@ -439,7 +439,7 @@ func TestReceiptMarshalBinary(t *testing.T) {
// 1559 Receipt // 1559 Receipt
buf.Reset() buf.Reset()
eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt}) eip1559Receipt.Bloom = CreateBloom(eip1559Receipt)
have, err = eip1559Receipt.MarshalBinary() have, err = eip1559Receipt.MarshalBinary()
if err != nil { if err != nil {
t.Fatalf("marshal binary error: %v", err) t.Fatalf("marshal binary error: %v", err)
@ -463,7 +463,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) {
if err := gotLegacyReceipt.UnmarshalBinary(legacyBinary); err != nil { if err := gotLegacyReceipt.UnmarshalBinary(legacyBinary); err != nil {
t.Fatalf("unmarshal binary error: %v", err) t.Fatalf("unmarshal binary error: %v", err)
} }
legacyReceipt.Bloom = CreateBloom(Receipts{legacyReceipt}) legacyReceipt.Bloom = CreateBloom(legacyReceipt)
if !reflect.DeepEqual(gotLegacyReceipt, legacyReceipt) { if !reflect.DeepEqual(gotLegacyReceipt, legacyReceipt) {
t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotLegacyReceipt, legacyReceipt) t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotLegacyReceipt, legacyReceipt)
} }
@ -474,7 +474,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) {
if err := gotAccessListReceipt.UnmarshalBinary(accessListBinary); err != nil { if err := gotAccessListReceipt.UnmarshalBinary(accessListBinary); err != nil {
t.Fatalf("unmarshal binary error: %v", err) t.Fatalf("unmarshal binary error: %v", err)
} }
accessListReceipt.Bloom = CreateBloom(Receipts{accessListReceipt}) accessListReceipt.Bloom = CreateBloom(accessListReceipt)
if !reflect.DeepEqual(gotAccessListReceipt, accessListReceipt) { if !reflect.DeepEqual(gotAccessListReceipt, accessListReceipt) {
t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotAccessListReceipt, accessListReceipt) t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", gotAccessListReceipt, accessListReceipt)
} }
@ -485,7 +485,7 @@ func TestReceiptUnmarshalBinary(t *testing.T) {
if err := got1559Receipt.UnmarshalBinary(eip1559RctBinary); err != nil { if err := got1559Receipt.UnmarshalBinary(eip1559RctBinary); err != nil {
t.Fatalf("unmarshal binary error: %v", err) t.Fatalf("unmarshal binary error: %v", err)
} }
eip1559Receipt.Bloom = CreateBloom(Receipts{eip1559Receipt}) eip1559Receipt.Bloom = CreateBloom(eip1559Receipt)
if !reflect.DeepEqual(got1559Receipt, eip1559Receipt) { if !reflect.DeepEqual(got1559Receipt, eip1559Receipt) {
t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", got1559Receipt, eip1559Receipt) t.Errorf("receipt unmarshalled from binary mismatch, got %v want %v", got1559Receipt, eip1559Receipt)
} }

View File

@ -22,39 +22,20 @@ import (
"github.com/holiman/uint256" "github.com/holiman/uint256"
) )
// ContractRef is a reference to the contract's backing object
type ContractRef interface {
Address() common.Address
}
// AccountRef implements ContractRef.
//
// Account references are used during EVM initialisation and
// its primary use is to fetch addresses. Removing this object
// proves difficult because of the cached jump destinations which
// are fetched from the parent contract (i.e. the caller), which
// is a ContractRef.
type AccountRef common.Address
// Address casts AccountRef to an Address
func (ar AccountRef) Address() common.Address { return (common.Address)(ar) }
// Contract represents an ethereum contract in the state database. It contains // Contract represents an ethereum contract in the state database. It contains
// the contract code, calling arguments. Contract implements ContractRef // the contract code, calling arguments. Contract implements ContractRef
type Contract struct { type Contract struct {
// CallerAddress is the result of the caller which initialised this // caller is the result of the caller which initialised this
// contract. However when the "call method" is delegated this value // contract. However, when the "call method" is delegated this
// needs to be initialised to that of the caller's caller. // value needs to be initialised to that of the caller's caller.
CallerAddress common.Address caller common.Address
caller ContractRef address common.Address
self ContractRef
jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis. jumpdests map[common.Hash]bitvec // Aggregated result of JUMPDEST analysis.
analysis bitvec // Locally cached result of JUMPDEST analysis analysis bitvec // Locally cached result of JUMPDEST analysis
Code []byte Code []byte
CodeHash common.Hash CodeHash common.Hash
CodeAddr *common.Address
Input []byte Input []byte
// is the execution frame represented by this object a contract deployment // is the execution frame represented by this object a contract deployment
@ -66,23 +47,18 @@ type Contract struct {
} }
// NewContract returns a new contract environment for the execution of EVM. // NewContract returns a new contract environment for the execution of EVM.
func NewContract(caller ContractRef, object ContractRef, value *uint256.Int, gas uint64) *Contract { func NewContract(caller common.Address, address common.Address, value *uint256.Int, gas uint64, jumpDests map[common.Hash]bitvec) *Contract {
c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object} // Initialize the jump analysis map if it's nil, mostly for tests
if jumpDests == nil {
if parent, ok := caller.(*Contract); ok { jumpDests = make(map[common.Hash]bitvec)
// Reuse JUMPDEST analysis from parent context if available. }
c.jumpdests = parent.jumpdests return &Contract{
} else { caller: caller,
c.jumpdests = make(map[common.Hash]bitvec) address: address,
jumpdests: jumpDests,
Gas: gas,
value: value,
} }
// Gas should be a pointer so it can safely be reduced through the run
// This pointer will be off the state transition
c.Gas = gas
// ensures a value is set
c.value = value
return c
} }
func (c *Contract) validJumpdest(dest *uint256.Int) bool { func (c *Contract) validJumpdest(dest *uint256.Int) bool {
@ -132,18 +108,6 @@ func (c *Contract) isCode(udest uint64) bool {
return c.analysis.codeSegment(udest) return c.analysis.codeSegment(udest)
} }
// AsDelegate sets the contract to be a delegate call and returns the current
// contract (for chaining calls)
func (c *Contract) AsDelegate() *Contract {
// NOTE: caller must, at all times be a contract. It should never happen
// that caller is something other than a Contract.
parent := c.caller.(*Contract)
c.CallerAddress = parent.CallerAddress
c.value = parent.value
return c
}
// GetOp returns the n'th element in the contract's byte array // GetOp returns the n'th element in the contract's byte array
func (c *Contract) GetOp(n uint64) OpCode { func (c *Contract) GetOp(n uint64) OpCode {
if n < uint64(len(c.Code)) { if n < uint64(len(c.Code)) {
@ -158,7 +122,7 @@ func (c *Contract) GetOp(n uint64) OpCode {
// Caller will recursively call caller when the contract is a delegate // Caller will recursively call caller when the contract is a delegate
// call, including that of caller's caller. // call, including that of caller's caller.
func (c *Contract) Caller() common.Address { func (c *Contract) Caller() common.Address {
return c.CallerAddress return c.caller
} }
// UseGas attempts the use gas and subtracts it and returns true on success // UseGas attempts the use gas and subtracts it and returns true on success
@ -186,7 +150,7 @@ func (c *Contract) RefundGas(gas uint64, logger *tracing.Hooks, reason tracing.G
// Address returns the contracts address // Address returns the contracts address
func (c *Contract) Address() common.Address { func (c *Contract) Address() common.Address {
return c.self.Address() return c.address
} }
// Value returns the contract's value (sent to it from it's caller) // Value returns the contract's value (sent to it from it's caller)
@ -194,18 +158,8 @@ func (c *Contract) Value() *uint256.Int {
return c.value return c.value
} }
// SetCallCode sets the code of the contract and address of the backing data // SetCallCode sets the code of the contract,
// object func (c *Contract) SetCallCode(hash common.Hash, code []byte) {
func (c *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
c.Code = code c.Code = code
c.CodeHash = hash c.CodeHash = hash
c.CodeAddr = addr
}
// SetCodeOptionalHash can be used to provide code, but it's optional to provide hash.
// In case hash is not provided, the jumpdest analysis will not be saved to the parent context
func (c *Contract) SetCodeOptionalHash(addr *common.Address, codeAndHash *codeAndHash) {
c.Code = codeAndHash.code
c.CodeHash = codeAndHash.hash
c.CodeAddr = addr
} }

View File

@ -338,13 +338,9 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC
} }
addr := common.Address(a.Bytes20()) addr := common.Address(a.Bytes20())
code := interpreter.evm.StateDB.GetCode(addr) code := interpreter.evm.StateDB.GetCode(addr)
contract := &Contract{
Code: code,
self: AccountRef(addr),
}
paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64()) paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64())
if !contract.IsSystemCall { if !scope.Contract.IsSystemCall {
statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false) statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(code)), false)
if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) { if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) {
scope.Contract.Gas = 0 scope.Contract.Gas = 0
return nil, ErrOutOfGas return nil, ErrOutOfGas

View File

@ -91,29 +91,40 @@ type EVM struct {
// Context provides auxiliary blockchain related information // Context provides auxiliary blockchain related information
Context BlockContext Context BlockContext
TxContext TxContext
// StateDB gives access to the underlying state // StateDB gives access to the underlying state
StateDB StateDB StateDB StateDB
// Depth is the current call stack
// depth is the current call stack
depth int depth int
// chainConfig contains information about the current chain // chainConfig contains information about the current chain
chainConfig *params.ChainConfig chainConfig *params.ChainConfig
// chain rules contains the chain rules for the current epoch // chain rules contains the chain rules for the current epoch
chainRules params.Rules chainRules params.Rules
// virtual machine configuration options used to initialise the
// evm. // virtual machine configuration options used to initialise the evm
Config Config Config Config
// global (to this context) ethereum virtual machine
// used throughout the execution of the tx. // global (to this context) ethereum virtual machine used throughout
// the execution of the tx
interpreter *EVMInterpreter interpreter *EVMInterpreter
// abort is used to abort the EVM calling operations // abort is used to abort the EVM calling operations
abort atomic.Bool abort atomic.Bool
// callGasTemp holds the gas available for the current call. This is needed because the // callGasTemp holds the gas available for the current call. This is needed because the
// available gas is calculated in gasCall* according to the 63/64 rule and later // available gas is calculated in gasCall* according to the 63/64 rule and later
// applied in opCall*. // applied in opCall*.
callGasTemp uint64 callGasTemp uint64
// precompiles holds the precompiled contracts for the current epoch // precompiles holds the precompiled contracts for the current epoch
precompiles map[common.Address]PrecompiledContract precompiles map[common.Address]PrecompiledContract
// jumpDests is the aggregated result of JUMPDEST analysis made through
// the life cycle of EVM.
jumpDests map[common.Hash]bitvec
} }
// NewEVM constructs an EVM instance with the supplied block context, state // NewEVM constructs an EVM instance with the supplied block context, state
@ -127,6 +138,7 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
Config: config, Config: config,
chainConfig: chainConfig, chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
jumpDests: make(map[common.Hash]bitvec),
} }
evm.precompiles = activePrecompiledContracts(evm.chainRules) evm.precompiles = activePrecompiledContracts(evm.chainRules)
evm.interpreter = NewEVMInterpreter(evm) evm.interpreter = NewEVMInterpreter(evm)
@ -165,18 +177,18 @@ func (evm *EVM) Interpreter() *EVMInterpreter {
return evm.interpreter return evm.interpreter
} }
func isSystemCall(caller ContractRef) bool { func isSystemCall(caller common.Address) bool {
return caller.Address() == params.SystemAddress return caller == params.SystemAddress
} }
// Call executes the contract associated with the addr with the given input as // Call executes the contract associated with the addr with the given input as
// parameters. It also handles any necessary value transfer required and takse // parameters. It also handles any necessary value transfer required and takse
// the necessary steps to create accounts and reverses the state in case of an // the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer. // execution error or failed value transfer.
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
// Capture the tracer start/end events in debug mode // Capture the tracer start/end events in debug mode
if evm.Config.Tracer != nil { if evm.Config.Tracer != nil {
evm.captureBegin(evm.depth, CALL, caller.Address(), addr, input, gas, value.ToBig()) evm.captureBegin(evm.depth, CALL, caller, addr, input, gas, value.ToBig())
defer func(startGas uint64) { defer func(startGas uint64) {
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
}(gas) }(gas)
@ -186,7 +198,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
return nil, gas, ErrDepth return nil, gas, ErrDepth
} }
// Fail if we're trying to transfer more than the available balance // Fail if we're trying to transfer more than the available balance
if !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { if !value.IsZero() && !evm.Context.CanTransfer(evm.StateDB, caller, value) {
return nil, gas, ErrInsufficientBalance return nil, gas, ErrInsufficientBalance
} }
snapshot := evm.StateDB.Snapshot() snapshot := evm.StateDB.Snapshot()
@ -209,23 +221,20 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
} }
evm.StateDB.CreateAccount(addr) evm.StateDB.CreateAccount(addr)
} }
evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value) evm.Context.Transfer(evm.StateDB, caller, addr, value)
if isPrecompile { if isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
} else { } else {
// Initialise a new contract and set the code that is to be used by the EVM. // Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only.
code := evm.resolveCode(addr) code := evm.resolveCode(addr)
if len(code) == 0 { if len(code) == 0 {
ret, err = nil, nil // gas is unchanged ret, err = nil, nil // gas is unchanged
} else { } else {
addrCopy := addr // The contract is a scoped environment for this execution context only.
// If the account has no code, we can abort here contract := NewContract(caller, addr, value, gas, evm.jumpDests)
// The depth-check is already done, and precompiles handled above
contract := NewContract(caller, AccountRef(addrCopy), value, gas)
contract.IsSystemCall = isSystemCall(caller) contract.IsSystemCall = isSystemCall(caller)
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), code) contract.SetCallCode(evm.resolveCodeHash(addr), code)
ret, err = evm.interpreter.Run(contract, input, false) ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas gas = contract.Gas
} }
@ -256,10 +265,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// //
// CallCode differs from Call in the sense that it executes the given address' // CallCode differs from Call in the sense that it executes the given address'
// code with the caller as context. // code with the caller as context.
func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) { func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
// Invoke tracer hooks that signal entering/exiting a call frame // Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Tracer != nil { if evm.Config.Tracer != nil {
evm.captureBegin(evm.depth, CALLCODE, caller.Address(), addr, input, gas, value.ToBig()) evm.captureBegin(evm.depth, CALLCODE, caller, addr, input, gas, value.ToBig())
defer func(startGas uint64) { defer func(startGas uint64) {
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
}(gas) }(gas)
@ -272,7 +281,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// Note although it's noop to transfer X ether to caller itself. But // Note although it's noop to transfer X ether to caller itself. But
// if caller doesn't have enough balance, it would be an error to allow // if caller doesn't have enough balance, it would be an error to allow
// over-charging itself. So the check here is necessary. // over-charging itself. So the check here is necessary.
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { if !evm.Context.CanTransfer(evm.StateDB, caller, value) {
return nil, gas, ErrInsufficientBalance return nil, gas, ErrInsufficientBalance
} }
var snapshot = evm.StateDB.Snapshot() var snapshot = evm.StateDB.Snapshot()
@ -281,11 +290,10 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
if p, isPrecompile := evm.precompile(addr); isPrecompile { if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
} else { } else {
addrCopy := addr
// Initialise a new contract and set the code that is to be used by the EVM. // Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only. // The contract is a scoped environment for this execution context only.
contract := NewContract(caller, AccountRef(caller.Address()), value, gas) contract := NewContract(caller, caller, value, gas, evm.jumpDests)
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr))
ret, err = evm.interpreter.Run(contract, input, false) ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas gas = contract.Gas
} }
@ -295,7 +303,6 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil {
evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution)
} }
gas = 0 gas = 0
} }
} }
@ -307,14 +314,11 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// //
// DelegateCall differs from CallCode in the sense that it executes the given address' // DelegateCall differs from CallCode in the sense that it executes the given address'
// code with the caller as context and the caller is set to the caller of the caller. // code with the caller as context and the caller is set to the caller of the caller.
func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
// Invoke tracer hooks that signal entering/exiting a call frame // Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Tracer != nil { if evm.Config.Tracer != nil {
// NOTE: caller must, at all times be a contract. It should never happen
// that caller is something other than a Contract.
parent := caller.(*Contract)
// DELEGATECALL inherits value from parent call // DELEGATECALL inherits value from parent call
evm.captureBegin(evm.depth, DELEGATECALL, caller.Address(), addr, input, gas, parent.value.ToBig()) evm.captureBegin(evm.depth, DELEGATECALL, caller, addr, input, gas, value.ToBig())
defer func(startGas uint64) { defer func(startGas uint64) {
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
}(gas) }(gas)
@ -329,10 +333,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
if p, isPrecompile := evm.precompile(addr); isPrecompile { if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
} else { } else {
addrCopy := addr
// Initialise a new contract and make initialise the delegate values // Initialise a new contract and make initialise the delegate values
contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() //
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) // Note: The value refers to the original value from the parent call.
contract := NewContract(originCaller, caller, value, gas, evm.jumpDests)
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr))
ret, err = evm.interpreter.Run(contract, input, false) ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas gas = contract.Gas
} }
@ -352,10 +357,10 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
// as parameters while disallowing any modifications to the state during the call. // as parameters while disallowing any modifications to the state during the call.
// Opcodes that attempt to perform such modifications will result in exceptions // Opcodes that attempt to perform such modifications will result in exceptions
// instead of performing the modifications. // instead of performing the modifications.
func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) {
// Invoke tracer hooks that signal entering/exiting a call frame // Invoke tracer hooks that signal entering/exiting a call frame
if evm.Config.Tracer != nil { if evm.Config.Tracer != nil {
evm.captureBegin(evm.depth, STATICCALL, caller.Address(), addr, input, gas, nil) evm.captureBegin(evm.depth, STATICCALL, caller, addr, input, gas, nil)
defer func(startGas uint64) { defer func(startGas uint64) {
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
}(gas) }(gas)
@ -380,14 +385,11 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
if p, isPrecompile := evm.precompile(addr); isPrecompile { if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer) ret, gas, err = RunPrecompiledContract(p, input, gas, evm.Config.Tracer)
} else { } else {
// At this point, we use a copy of address. If we don't, the go compiler will
// leak the 'contract' to the outer scope, and make allocation for 'contract'
// even if the actual execution ends on RunPrecompiled above.
addrCopy := addr
// Initialise a new contract and set the code that is to be used by the EVM. // Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only. // The contract is a scoped environment for this execution context only.
contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas) contract := NewContract(caller, addr, new(uint256.Int), gas, evm.jumpDests)
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr))
// When an error was returned by the EVM or when setting the creation code // When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally // above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in Homestead this also counts for code storage gas errors. // when we're in Homestead this also counts for code storage gas errors.
@ -407,22 +409,10 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
return ret, gas, err return ret, gas, err
} }
type codeAndHash struct {
code []byte
hash common.Hash
}
func (c *codeAndHash) Hash() common.Hash {
if c.hash == (common.Hash{}) {
c.hash = crypto.Keccak256Hash(c.code)
}
return c.hash
}
// create creates a new contract using code as deployment code. // create creates a new contract using code as deployment code.
func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *uint256.Int, address common.Address, typ OpCode) (ret []byte, createAddress common.Address, leftOverGas uint64, err error) { func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *uint256.Int, address common.Address, typ OpCode) (ret []byte, createAddress common.Address, leftOverGas uint64, err error) {
if evm.Config.Tracer != nil { if evm.Config.Tracer != nil {
evm.captureBegin(evm.depth, typ, caller.Address(), address, codeAndHash.code, gas, value.ToBig()) evm.captureBegin(evm.depth, typ, caller, address, code, gas, value.ToBig())
defer func(startGas uint64) { defer func(startGas uint64) {
evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err) evm.captureEnd(evm.depth, startGas, leftOverGas, ret, err)
}(gas) }(gas)
@ -432,14 +422,14 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
if evm.depth > int(params.CallCreateDepth) { if evm.depth > int(params.CallCreateDepth) {
return nil, common.Address{}, gas, ErrDepth return nil, common.Address{}, gas, ErrDepth
} }
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { if !evm.Context.CanTransfer(evm.StateDB, caller, value) {
return nil, common.Address{}, gas, ErrInsufficientBalance return nil, common.Address{}, gas, ErrInsufficientBalance
} }
nonce := evm.StateDB.GetNonce(caller.Address()) nonce := evm.StateDB.GetNonce(caller)
if nonce+1 < nonce { if nonce+1 < nonce {
return nil, common.Address{}, gas, ErrNonceUintOverflow return nil, common.Address{}, gas, ErrNonceUintOverflow
} }
evm.StateDB.SetNonce(caller.Address(), nonce+1, tracing.NonceChangeContractCreator) evm.StateDB.SetNonce(caller, nonce+1, tracing.NonceChangeContractCreator)
// Charge the contract creation init gas in verkle mode // Charge the contract creation init gas in verkle mode
if evm.chainRules.IsEIP4762 { if evm.chainRules.IsEIP4762 {
@ -500,15 +490,18 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
} }
gas = gas - statelessGas gas = gas - statelessGas
} }
evm.Context.Transfer(evm.StateDB, caller.Address(), address, value) evm.Context.Transfer(evm.StateDB, caller, address, value)
// Initialise a new contract and set the code that is to be used by the EVM. // Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only. // The contract is a scoped environment for this execution context only.
contract := NewContract(caller, AccountRef(address), value, gas) contract := NewContract(caller, address, value, gas, evm.jumpDests)
contract.SetCodeOptionalHash(&address, codeAndHash)
// Explicitly set the code to a null hash to prevent caching of jump analysis
// for the initialization code.
contract.SetCallCode(common.Hash{}, code)
contract.IsDeployment = true contract.IsDeployment = true
ret, err = evm.initNewContract(contract, address, value) ret, err = evm.initNewContract(contract, address)
if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) { if err != nil && (evm.chainRules.IsHomestead || err != ErrCodeStoreOutOfGas) {
evm.StateDB.RevertToSnapshot(snapshot) evm.StateDB.RevertToSnapshot(snapshot)
if err != ErrExecutionReverted { if err != ErrExecutionReverted {
@ -520,7 +513,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
// initNewContract runs a new contract's creation code, performs checks on the // initNewContract runs a new contract's creation code, performs checks on the
// resulting code that is to be deployed, and consumes necessary gas. // resulting code that is to be deployed, and consumes necessary gas.
func (evm *EVM) initNewContract(contract *Contract, address common.Address, value *uint256.Int) ([]byte, error) { func (evm *EVM) initNewContract(contract *Contract, address common.Address) ([]byte, error) {
ret, err := evm.interpreter.Run(contract, nil, false) ret, err := evm.interpreter.Run(contract, nil, false)
if err != nil { if err != nil {
return ret, err return ret, err
@ -552,19 +545,18 @@ func (evm *EVM) initNewContract(contract *Contract, address common.Address, valu
} }
// Create creates a new contract using code as deployment code. // Create creates a new contract using code as deployment code.
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) contractAddr = crypto.CreateAddress(caller, evm.StateDB.GetNonce(caller))
return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr, CREATE) return evm.create(caller, code, gas, value, contractAddr, CREATE)
} }
// Create2 creates a new contract using code as deployment code. // Create2 creates a new contract using code as deployment code.
// //
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:] // The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
codeAndHash := &codeAndHash{code: code} contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), crypto.Keccak256(code))
contractAddr = crypto.CreateAddress2(caller.Address(), salt.Bytes32(), codeAndHash.Hash().Bytes()) return evm.create(caller, code, gas, endowment, contractAddr, CREATE2)
return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2)
} }
// resolveCode returns the code associated with the provided account. After // resolveCode returns the code associated with the provided account. After

View File

@ -97,7 +97,7 @@ func TestEIP2200(t *testing.T) {
} }
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}}) evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
_, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int)) _, gas, err := evm.Call(common.Address{}, address, nil, tt.gaspool, new(uint256.Int))
if !errors.Is(err, tt.failure) { if !errors.Is(err, tt.failure) {
t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure) t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
} }
@ -153,7 +153,7 @@ func TestCreateGas(t *testing.T) {
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, config) evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, config)
var startGas = uint64(testGas) var startGas = uint64(testGas)
ret, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int)) ret, gas, err := evm.Call(common.Address{}, address, nil, startGas, new(uint256.Int))
if err != nil { if err != nil {
return false return false
} }

View File

@ -677,7 +677,7 @@ func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]b
scope.Contract.UseGas(gas, interpreter.evm.Config.Tracer, tracing.GasChangeCallContractCreation) scope.Contract.UseGas(gas, interpreter.evm.Config.Tracer, tracing.GasChangeCallContractCreation)
res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract, input, gas, &value) res, addr, returnGas, suberr := interpreter.evm.Create(scope.Contract.Address(), input, gas, &value)
// Push item on the stack based on the returned error. If the ruleset is // Push item on the stack based on the returned error. If the ruleset is
// homestead we must check for CodeStoreOutOfGasError (homestead only // homestead we must check for CodeStoreOutOfGasError (homestead only
// rule) and treat as an error, if the ruleset is frontier we must // rule) and treat as an error, if the ruleset is frontier we must
@ -718,7 +718,7 @@ func opCreate2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]
scope.Contract.UseGas(gas, interpreter.evm.Config.Tracer, tracing.GasChangeCallContractCreation2) scope.Contract.UseGas(gas, interpreter.evm.Config.Tracer, tracing.GasChangeCallContractCreation2)
// reuse size int for stackvalue // reuse size int for stackvalue
stackvalue := size stackvalue := size
res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract, input, gas, res, addr, returnGas, suberr := interpreter.evm.Create2(scope.Contract.Address(), input, gas,
&endowment, &salt) &endowment, &salt)
// Push item on the stack based on the returned error. // Push item on the stack based on the returned error.
if suberr != nil { if suberr != nil {
@ -755,7 +755,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
if !value.IsZero() { if !value.IsZero() {
gas += params.CallStipend gas += params.CallStipend
} }
ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, &value) ret, returnGas, err := interpreter.evm.Call(scope.Contract.Address(), toAddr, args, gas, &value)
if err != nil { if err != nil {
temp.Clear() temp.Clear()
@ -789,7 +789,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
gas += params.CallStipend gas += params.CallStipend
} }
ret, returnGas, err := interpreter.evm.CallCode(scope.Contract, toAddr, args, gas, &value) ret, returnGas, err := interpreter.evm.CallCode(scope.Contract.Address(), toAddr, args, gas, &value)
if err != nil { if err != nil {
temp.Clear() temp.Clear()
} else { } else {
@ -818,7 +818,7 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
// Get arguments from the memory. // Get arguments from the memory.
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64()) args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
ret, returnGas, err := interpreter.evm.DelegateCall(scope.Contract, toAddr, args, gas) ret, returnGas, err := interpreter.evm.DelegateCall(scope.Contract.Caller(), scope.Contract.Address(), toAddr, args, gas, scope.Contract.value)
if err != nil { if err != nil {
temp.Clear() temp.Clear()
} else { } else {
@ -847,7 +847,7 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
// Get arguments from the memory. // Get arguments from the memory.
args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64()) args := scope.Memory.GetPtr(inOffset.Uint64(), inSize.Uint64())
ret, returnGas, err := interpreter.evm.StaticCall(scope.Contract, toAddr, args, gas) ret, returnGas, err := interpreter.evm.StaticCall(scope.Contract.Address(), toAddr, args, gas)
if err != nil { if err != nil {
temp.Clear() temp.Clear()
} else { } else {

View File

@ -49,14 +49,6 @@ var alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffff
var commonParams []*twoOperandParams var commonParams []*twoOperandParams
var twoOpMethods map[string]executionFunc var twoOpMethods map[string]executionFunc
type contractRef struct {
addr common.Address
}
func (c contractRef) Address() common.Address {
return c.addr
}
func init() { func init() {
// Params is a list of common edgecases that should be used for some common tests // Params is a list of common edgecases that should be used for some common tests
params := []string{ params := []string{
@ -575,8 +567,7 @@ func TestOpTstore(t *testing.T) {
mem = NewMemory() mem = NewMemory()
caller = common.Address{} caller = common.Address{}
to = common.Address{1} to = common.Address{1}
contractRef = contractRef{caller} contract = NewContract(caller, to, new(uint256.Int), 0, nil)
contract = NewContract(contractRef, AccountRef(to), new(uint256.Int), 0)
scopeContext = ScopeContext{mem, stack, contract} scopeContext = ScopeContext{mem, stack, contract}
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700") value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
) )

View File

@ -17,8 +17,6 @@
package vm package vm
import ( import (
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/stateless" "github.com/ethereum/go-ethereum/core/stateless"
@ -104,16 +102,3 @@ type StateDB interface {
// Finalise must be invoked at the end of a transaction // Finalise must be invoked at the end of a transaction
Finalise(bool) Finalise(bool)
} }
// CallContext provides a basic interface for the EVM calling conventions. The EVM
// depends on this context being implemented for doing subcalls and initialising new EVM contracts.
type CallContext interface {
// Call calls another contract.
Call(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
// CallCode takes another contracts code and execute within our own context
CallCode(env *EVM, me ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error)
// DelegateCall is same as CallCode except sender and value is propagated from parent to child scope
DelegateCall(env *EVM, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error)
// Create creates a new contract
Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error)
}

View File

@ -53,7 +53,7 @@ func TestLoopInterrupt(t *testing.T) {
timeout := make(chan bool) timeout := make(chan bool)
go func(evm *EVM) { go func(evm *EVM) {
_, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(uint256.Int)) _, _, err := evm.Call(common.Address{}, address, nil, math.MaxUint64, new(uint256.Int))
errChannel <- err errChannel <- err
}(evm) }(evm)

View File

@ -128,7 +128,6 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
var ( var (
address = common.BytesToAddress([]byte("contract")) address = common.BytesToAddress([]byte("contract"))
vmenv = NewEnv(cfg) vmenv = NewEnv(cfg)
sender = vm.AccountRef(cfg.Origin)
rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
) )
if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxStart != nil { if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxStart != nil {
@ -143,7 +142,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
cfg.State.SetCode(address, code) cfg.State.SetCode(address, code)
// Call the code with the given configuration. // Call the code with the given configuration.
ret, leftOverGas, err := vmenv.Call( ret, leftOverGas, err := vmenv.Call(
sender, cfg.Origin,
common.BytesToAddress([]byte("contract")), common.BytesToAddress([]byte("contract")),
input, input,
cfg.GasLimit, cfg.GasLimit,
@ -166,9 +165,8 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
} }
var ( var (
vmenv = NewEnv(cfg) vmenv = NewEnv(cfg)
sender = vm.AccountRef(cfg.Origin) rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
) )
if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxStart != nil { if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxStart != nil {
cfg.EVMConfig.Tracer.OnTxStart(vmenv.GetVMContext(), types.NewTx(&types.LegacyTx{Data: input, Value: cfg.Value, Gas: cfg.GasLimit}), cfg.Origin) cfg.EVMConfig.Tracer.OnTxStart(vmenv.GetVMContext(), types.NewTx(&types.LegacyTx{Data: input, Value: cfg.Value, Gas: cfg.GasLimit}), cfg.Origin)
@ -179,7 +177,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, nil, vm.ActivePrecompiles(rules), nil) cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, nil, vm.ActivePrecompiles(rules), nil)
// Call the code with the given configuration. // Call the code with the given configuration.
code, address, leftOverGas, err := vmenv.Create( code, address, leftOverGas, err := vmenv.Create(
sender, cfg.Origin,
input, input,
cfg.GasLimit, cfg.GasLimit,
uint256.MustFromBig(cfg.Value), uint256.MustFromBig(cfg.Value),
@ -200,7 +198,6 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
var ( var (
vmenv = NewEnv(cfg) vmenv = NewEnv(cfg)
sender = vm.AccountRef(cfg.Origin)
statedb = cfg.State statedb = cfg.State
rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
) )
@ -214,7 +211,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
// Call the code with the given configuration. // Call the code with the given configuration.
ret, leftOverGas, err := vmenv.Call( ret, leftOverGas, err := vmenv.Call(
sender, cfg.Origin,
address, address,
input, input,
cfg.GasLimit, cfg.GasLimit,

View File

@ -33,6 +33,8 @@ import (
"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/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params/forks"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
@ -95,6 +97,16 @@ type SimulatedBeacon struct {
lastBlockTime uint64 lastBlockTime uint64
} }
func payloadVersion(config *params.ChainConfig, time uint64) engine.PayloadVersion {
switch config.LatestFork(time) {
case forks.Prague, forks.Cancun:
return engine.PayloadV3
case forks.Paris, forks.Shanghai:
return engine.PayloadV2
}
panic("invalid fork, simulated beacon needs to be started post-merge")
}
// NewSimulatedBeacon constructs a new simulated beacon chain. // NewSimulatedBeacon constructs a new simulated beacon chain.
func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, error) { func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, error) {
block := eth.BlockChain().CurrentBlock() block := eth.BlockChain().CurrentBlock()
@ -107,7 +119,8 @@ func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, err
// if genesis block, send forkchoiceUpdated to trigger transition to PoS // if genesis block, send forkchoiceUpdated to trigger transition to PoS
if block.Number.Sign() == 0 { if block.Number.Sign() == 0 {
if _, err := engineAPI.ForkchoiceUpdatedV3(current, nil); err != nil { version := payloadVersion(eth.BlockChain().Config(), block.Time)
if _, err := engineAPI.forkchoiceUpdated(current, nil, version, false); err != nil {
return nil, err return nil, err
} }
} }
@ -171,6 +184,8 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
return fmt.Errorf("failed to sync txpool: %w", err) return fmt.Errorf("failed to sync txpool: %w", err)
} }
version := payloadVersion(c.eth.BlockChain().Config(), timestamp)
var random [32]byte var random [32]byte
rand.Read(random[:]) rand.Read(random[:])
fcResponse, err := c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, &engine.PayloadAttributes{ fcResponse, err := c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, &engine.PayloadAttributes{
@ -179,7 +194,7 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
Withdrawals: withdrawals, Withdrawals: withdrawals,
Random: random, Random: random,
BeaconRoot: &common.Hash{}, BeaconRoot: &common.Hash{},
}, engine.PayloadV3, false) }, version, false)
if err != nil { if err != nil {
return err return err
} }
@ -204,28 +219,39 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
} }
} }
// Independently calculate the blob hashes from sidecars. var (
blobHashes := make([]common.Hash, 0) blobHashes []common.Hash
if envelope.BlobsBundle != nil { beaconRoot *common.Hash
hasher := sha256.New() requests [][]byte
for _, commit := range envelope.BlobsBundle.Commitments { )
var c kzg4844.Commitment // Compute post-shanghai fields
if len(commit) != len(c) { if version > engine.PayloadV2 {
return errors.New("invalid commitment length") // Independently calculate the blob hashes from sidecars.
blobHashes = make([]common.Hash, 0)
if envelope.BlobsBundle != nil {
hasher := sha256.New()
for _, commit := range envelope.BlobsBundle.Commitments {
var c kzg4844.Commitment
if len(commit) != len(c) {
return errors.New("invalid commitment length")
}
copy(c[:], commit)
blobHashes = append(blobHashes, kzg4844.CalcBlobHashV1(hasher, &c))
} }
copy(c[:], commit)
blobHashes = append(blobHashes, kzg4844.CalcBlobHashV1(hasher, &c))
} }
beaconRoot = &common.Hash{}
requests = envelope.Requests
} }
// Mark the payload as canon // Mark the payload as canon
_, err = c.engineAPI.newPayload(*payload, blobHashes, &common.Hash{}, envelope.Requests, false) _, err = c.engineAPI.newPayload(*payload, blobHashes, beaconRoot, requests, false)
if err != nil { if err != nil {
return err return err
} }
c.setCurrentState(payload.BlockHash, finalizedHash) c.setCurrentState(payload.BlockHash, finalizedHash)
// Mark the block containing the payload as canonical // Mark the block containing the payload as canonical
if _, err = c.engineAPI.ForkchoiceUpdatedV3(c.curForkchoiceState, nil); err != nil { if _, err = c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, nil, version, false); err != nil {
return err return err
} }
c.lastBlockTime = payload.Timestamp c.lastBlockTime = payload.Timestamp

View File

@ -42,7 +42,7 @@ func makeReceipt(addr common.Address) *types.Receipt {
receipt.Logs = []*types.Log{ receipt.Logs = []*types.Log{
{Address: addr}, {Address: addr},
} }
receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) receipt.Bloom = types.CreateBloom(receipt)
return receipt return receipt
} }

View File

@ -89,7 +89,7 @@ type TxPool interface {
} }
// MakeProtocols constructs the P2P protocol definitions for `eth`. // MakeProtocols constructs the P2P protocol definitions for `eth`.
func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2p.Protocol { func MakeProtocols(backend Backend, network uint64, disc enode.Iterator) []p2p.Protocol {
protocols := make([]p2p.Protocol, 0, len(ProtocolVersions)) protocols := make([]p2p.Protocol, 0, len(ProtocolVersions))
for _, version := range ProtocolVersions { for _, version := range ProtocolVersions {
protocols = append(protocols, p2p.Protocol{ protocols = append(protocols, p2p.Protocol{
@ -110,7 +110,8 @@ func MakeProtocols(backend Backend, network uint64, dnsdisc enode.Iterator) []p2
PeerInfo: func(id enode.ID) interface{} { PeerInfo: func(id enode.ID) interface{} {
return backend.PeerInfo(id) return backend.PeerInfo(id)
}, },
Attributes: []enr.Entry{currentENREntry(backend.Chain())}, DialCandidates: disc,
Attributes: []enr.Entry{currentENREntry(backend.Chain())},
}) })
} }
return protocols return protocols

View File

@ -33,19 +33,6 @@ import (
"github.com/holiman/uint256" "github.com/holiman/uint256"
) )
type account struct{}
func (account) SubBalance(amount *big.Int) {}
func (account) AddBalance(amount *big.Int) {}
func (account) SetAddress(common.Address) {}
func (account) Value() *big.Int { return nil }
func (account) SetBalance(*uint256.Int) {}
func (account) SetNonce(uint64) {}
func (account) Balance() *uint256.Int { return nil }
func (account) Address() common.Address { return common.Address{} }
func (account) SetCode(common.Hash, []byte) {}
func (account) ForEachStorage(cb func(key, value common.Hash) bool) {}
type dummyStatedb struct { type dummyStatedb struct {
state.StateDB state.StateDB
} }
@ -68,7 +55,7 @@ func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCo
gasLimit uint64 = 31000 gasLimit uint64 = 31000
startGas uint64 = 10000 startGas uint64 = 10000
value = uint256.NewInt(0) value = uint256.NewInt(0)
contract = vm.NewContract(account{}, account{}, value, startGas) contract = vm.NewContract(common.Address{}, common.Address{}, value, startGas, nil)
) )
evm.SetTxContext(vmctx.txCtx) evm.SetTxContext(vmctx.txCtx)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0} contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
@ -190,7 +177,7 @@ func TestHaltBetweenSteps(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
scope := &vm.ScopeContext{ scope := &vm.ScopeContext{
Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0), Contract: vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil),
} }
evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks}) evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
evm.SetTxContext(vm.TxContext{GasPrice: big.NewInt(1)}) evm.SetTxContext(vm.TxContext{GasPrice: big.NewInt(1)})
@ -288,7 +275,7 @@ func TestEnterExit(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
scope := &vm.ScopeContext{ scope := &vm.ScopeContext{
Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0), Contract: vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil),
} }
tracer.OnEnter(1, byte(vm.CALL), scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int)) tracer.OnEnter(1, byte(vm.CALL), scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int))
tracer.OnExit(1, []byte{}, 400, nil, false) tracer.OnExit(1, []byte{}, 400, nil, false)

View File

@ -29,22 +29,6 @@ import (
"github.com/holiman/uint256" "github.com/holiman/uint256"
) )
type dummyContractRef struct {
calledForEach bool
}
func (dummyContractRef) Address() common.Address { return common.Address{} }
func (dummyContractRef) Value() *big.Int { return new(big.Int) }
func (dummyContractRef) SetCode(common.Hash, []byte) {}
func (d *dummyContractRef) ForEachStorage(callback func(key, value common.Hash) bool) {
d.calledForEach = true
}
func (d *dummyContractRef) SubBalance(amount *big.Int) {}
func (d *dummyContractRef) AddBalance(amount *big.Int) {}
func (d *dummyContractRef) SetBalance(*big.Int) {}
func (d *dummyContractRef) SetNonce(uint64) {}
func (d *dummyContractRef) Balance() *big.Int { return new(big.Int) }
type dummyStatedb struct { type dummyStatedb struct {
state.StateDB state.StateDB
} }
@ -59,7 +43,7 @@ func TestStoreCapture(t *testing.T) {
var ( var (
logger = NewStructLogger(nil) logger = NewStructLogger(nil)
evm = vm.NewEVM(vm.BlockContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()}) evm = vm.NewEVM(vm.BlockContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()})
contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(uint256.Int), 100000) contract = vm.NewContract(common.Address{}, common.Address{}, new(uint256.Int), 100000, nil)
) )
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)} contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
var index common.Hash var index common.Hash

View File

@ -85,11 +85,23 @@ func (ec *Client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Blo
return ec.getBlock(ctx, "eth_getBlockByHash", hash, true) return ec.getBlock(ctx, "eth_getBlockByHash", hash, true)
} }
// BlockByNumber returns a block from the current canonical chain. If number is nil, the // BlockByNumber returns a block from the current canonical chain.
// latest known block is returned. // If `number` is nil, the latest known block is returned.
// //
// Note that loading full blocks requires two requests. Use HeaderByNumber // Use `HeaderByNumber` if you don't need full transaction data or uncle headers.
// if you don't need all transactions or uncle headers. //
// Supported special block number tags:
// - `earliest` : The genesis (earliest) block
// - `latest` : The most recently included block
// - `safe` : The latest safe head block
// - `finalized` : The latest finalized block
// - `pending` : The pending block
//
// Example usage:
//
// ```go
// BlockByNumber(context.Background(), big.NewInt(int64(rpc.LatestBlockNumber)))
// ```
func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
return ec.getBlock(ctx, "eth_getBlockByNumber", toBlockNumArg(number), true) return ec.getBlock(ctx, "eth_getBlockByNumber", toBlockNumArg(number), true)
} }
@ -210,8 +222,21 @@ func (ec *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.He
return head, err return head, err
} }
// HeaderByNumber returns a block header from the current canonical chain. If number is // HeaderByNumber returns a block header from the current canonical chain.
// nil, the latest known header is returned. // If `number` is nil, the latest known block header is returned.
//
// Supported special block number tags:
// - `earliest` : The genesis (earliest) block
// - `latest` : The most recently included block
// - `safe` : The latest safe head block
// - `finalized` : The latest finalized block
// - `pending` : The pending block
//
// Example usage:
//
// ```go
// HeaderByNumber(context.Background(), big.NewInt(int64(rpc.LatestBlockNumber)))
// ```
func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
var head *types.Header var head *types.Header
err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", toBlockNumArg(number), false) err := ec.c.CallContext(ctx, &head, "eth_getBlockByNumber", toBlockNumArg(number), false)

2
go.mod
View File

@ -1,6 +1,6 @@
module github.com/ethereum/go-ethereum module github.com/ethereum/go-ethereum
go 1.22.0 go 1.23.0
require ( require (
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0

View File

@ -78,6 +78,7 @@ func TestEra1Builder(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to open era: %v", err) t.Fatalf("failed to open era: %v", err)
} }
defer e.Close()
it, err := NewRawIterator(e) it, err := NewRawIterator(e)
if err != nil { if err != nil {
t.Fatalf("failed to make iterator: %s", err) t.Fatalf("failed to make iterator: %s", err)

View File

@ -18,6 +18,7 @@ package p2p
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"encoding"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
@ -135,6 +136,13 @@ type configNAT struct {
nat.Interface nat.Interface
} }
func (w *configNAT) MarshalText() ([]byte, error) {
if tm, ok := w.Interface.(encoding.TextMarshaler); ok {
return tm.MarshalText()
}
return nil, fmt.Errorf("NAT specification %#v cannot be marshaled", w.Interface)
}
func (w *configNAT) UnmarshalText(input []byte) error { func (w *configNAT) UnmarshalText(input []byte) error {
n, err := nat.Parse(string(input)) n, err := nat.Parse(string(input))
if err != nil { if err != nil {

View File

@ -317,10 +317,17 @@ var (
Max: 9, Max: 9,
UpdateFraction: 5007716, UpdateFraction: 5007716,
} }
// DefaultOsakaBlobConfig is the default blob configuration for the Osaka fork.
DefaultOsakaBlobConfig = &BlobConfig{
Target: 6,
Max: 9,
UpdateFraction: 5007716,
}
// DefaultBlobSchedule is the latest configured blob schedule for test chains. // DefaultBlobSchedule is the latest configured blob schedule for test chains.
DefaultBlobSchedule = &BlobScheduleConfig{ DefaultBlobSchedule = &BlobScheduleConfig{
Cancun: DefaultCancunBlobConfig, Cancun: DefaultCancunBlobConfig,
Prague: DefaultPragueBlobConfig, Prague: DefaultPragueBlobConfig,
Osaka: DefaultOsakaBlobConfig,
} }
) )
@ -501,6 +508,7 @@ type BlobConfig struct {
type BlobScheduleConfig struct { type BlobScheduleConfig struct {
Cancun *BlobConfig `json:"cancun,omitempty"` Cancun *BlobConfig `json:"cancun,omitempty"`
Prague *BlobConfig `json:"prague,omitempty"` Prague *BlobConfig `json:"prague,omitempty"`
Osaka *BlobConfig `json:"osaka,omitempty"`
Verkle *BlobConfig `json:"verkle,omitempty"` Verkle *BlobConfig `json:"verkle,omitempty"`
} }
@ -732,16 +740,17 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
}{ }{
{name: "cancun", timestamp: c.CancunTime, config: bsc.Cancun}, {name: "cancun", timestamp: c.CancunTime, config: bsc.Cancun},
{name: "prague", timestamp: c.PragueTime, config: bsc.Prague}, {name: "prague", timestamp: c.PragueTime, config: bsc.Prague},
{name: "osaka", timestamp: c.OsakaTime, config: bsc.Osaka},
} { } {
if cur.config != nil { if cur.config != nil {
if err := cur.config.validate(); err != nil { if err := cur.config.validate(); err != nil {
return fmt.Errorf("invalid blob configuration for fork %s: %v", cur.name, err) return fmt.Errorf("invalid chain configuration in blobSchedule for fork %q: %v", cur.name, err)
} }
} }
if cur.timestamp != nil { if cur.timestamp != nil {
// If the fork is configured, a blob schedule must be defined for it. // If the fork is configured, a blob schedule must be defined for it.
if cur.config == nil { if cur.config == nil {
return fmt.Errorf("unsupported fork configuration: missing blob configuration entry for %v in schedule", cur.name) return fmt.Errorf("invalid chain configuration: missing entry for fork %q in blobSchedule", cur.name)
} }
} }
} }

View File

@ -431,6 +431,11 @@ var Forks = map[string]*params.ChainConfig{
PragueTime: u64(0), PragueTime: u64(0),
OsakaTime: u64(0), OsakaTime: u64(0),
DepositContractAddress: params.MainnetChainConfig.DepositContractAddress, DepositContractAddress: params.MainnetChainConfig.DepositContractAddress,
BlobScheduleConfig: &params.BlobScheduleConfig{
Cancun: params.DefaultCancunBlobConfig,
Prague: params.DefaultPragueBlobConfig,
Osaka: params.DefaultOsakaBlobConfig,
},
}, },
"PragueToOsakaAtTime15k": { "PragueToOsakaAtTime15k": {
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
@ -453,6 +458,11 @@ var Forks = map[string]*params.ChainConfig{
PragueTime: u64(0), PragueTime: u64(0),
OsakaTime: u64(15_000), OsakaTime: u64(15_000),
DepositContractAddress: params.MainnetChainConfig.DepositContractAddress, DepositContractAddress: params.MainnetChainConfig.DepositContractAddress,
BlobScheduleConfig: &params.BlobScheduleConfig{
Cancun: params.DefaultCancunBlobConfig,
Prague: params.DefaultPragueBlobConfig,
Osaka: params.DefaultOsakaBlobConfig,
},
}, },
} }

View File

@ -310,8 +310,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
evm.SetTxContext(txContext) evm.SetTxContext(txContext)
// Create "contract" for sender to cache code analysis. // Create "contract" for sender to cache code analysis.
sender := vm.NewContract(vm.AccountRef(msg.From), vm.AccountRef(msg.From), sender := vm.NewContract(msg.From, msg.From, nil, 0, nil)
nil, 0)
var ( var (
gasUsed uint64 gasUsed uint64
@ -326,7 +325,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
start := time.Now() start := time.Now()
// Execute the message. // Execute the message.
_, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, uint256.MustFromBig(msg.Value)) _, leftOverGas, err := evm.Call(sender.Address(), *msg.To, msg.Data, msg.GasLimit, uint256.MustFromBig(msg.Value))
if err != nil { if err != nil {
b.Error(err) b.Error(err)
return return

View File

@ -37,16 +37,13 @@ func FuzzStackTrie(f *testing.F) {
} }
func fuzz(data []byte, debugging bool) { func fuzz(data []byte, debugging bool) {
// This spongeDb is used to check the sequence of disk-db-writes
var ( var (
input = bytes.NewReader(data) input = bytes.NewReader(data)
spongeA = &spongeDb{sponge: crypto.NewKeccakState()} dbA = newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
dbA = newTestDatabase(rawdb.NewDatabase(spongeA), rawdb.HashScheme) trieA = NewEmpty(dbA)
trieA = NewEmpty(dbA) memDB = rawdb.NewMemoryDatabase()
spongeB = &spongeDb{sponge: crypto.NewKeccakState()} trieB = NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
dbB = newTestDatabase(rawdb.NewDatabase(spongeB), rawdb.HashScheme) rawdb.WriteTrieNode(memDB, common.Hash{}, path, hash, blob, rawdb.HashScheme)
trieB = NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(spongeB, common.Hash{}, path, hash, blob, dbB.Scheme())
}) })
vals []*kv vals []*kv
maxElements = 10000 maxElements = 10000
@ -55,13 +52,17 @@ func fuzz(data []byte, debugging bool) {
) )
// Fill the trie with elements // Fill the trie with elements
for i := 0; input.Len() > 0 && i < maxElements; i++ { for i := 0; input.Len() > 0 && i < maxElements; i++ {
// Build the key
k := make([]byte, 32) k := make([]byte, 32)
input.Read(k) input.Read(k)
// Build the val
var a uint16 var a uint16
binary.Read(input, binary.LittleEndian, &a) binary.Read(input, binary.LittleEndian, &a)
a = 1 + a%100 a = 1 + a%100
v := make([]byte, a) v := make([]byte, a)
input.Read(v) input.Read(v)
if input.Len() == 0 { if input.Len() == 0 {
// If it was exhausted while reading, the value may be all zeroes, // If it was exhausted while reading, the value may be all zeroes,
// thus 'deletion' which is not supported on stacktrie // thus 'deletion' which is not supported on stacktrie
@ -73,6 +74,7 @@ func fuzz(data []byte, debugging bool) {
} }
keys[string(k)] = struct{}{} keys[string(k)] = struct{}{}
vals = append(vals, &kv{k: k, v: v}) vals = append(vals, &kv{k: k, v: v})
trieA.MustUpdate(k, v) trieA.MustUpdate(k, v)
} }
if len(vals) == 0 { if len(vals) == 0 {
@ -99,11 +101,6 @@ func fuzz(data []byte, debugging bool) {
if rootA != rootB { if rootA != rootB {
panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootB)) panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootB))
} }
sumA := spongeA.sponge.Sum(nil)
sumB := spongeB.sponge.Sum(nil)
if !bytes.Equal(sumA, sumB) {
panic(fmt.Sprintf("sequence differ: (trie) %x != %x (stacktrie)", sumA, sumB))
}
// Ensure all the nodes are persisted correctly // Ensure all the nodes are persisted correctly
var ( var (

View File

@ -779,6 +779,7 @@ func TestCommitAfterHash(t *testing.T) {
func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) { func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
// Make the random benchmark deterministic // Make the random benchmark deterministic
random := rand.New(rand.NewSource(0)) random := rand.New(rand.NewSource(0))
// Create a realistic account trie to hash // Create a realistic account trie to hash
addresses = make([][20]byte, size) addresses = make([][20]byte, size)
for i := 0; i < len(addresses); i++ { for i := 0; i < len(addresses); i++ {
@ -795,13 +796,18 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
) )
// The big.Rand function is not deterministic with regards to 64 vs 32 bit systems, // The big.Rand function is not deterministic with regards to 64 vs 32 bit systems,
// and will consume different amount of data from the rand source. // and will consume different amount of data from the rand source.
//balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil)) // balance = new(big.Int).Rand(random, new(big.Int).Exp(common.Big2, common.Big256, nil))
// Therefore, we instead just read via byte buffer // Therefore, we instead just read via byte buffer
numBytes := random.Uint32() % 33 // [0, 32] bytes numBytes := random.Uint32() % 33 // [0, 32] bytes
balanceBytes := make([]byte, numBytes) balanceBytes := make([]byte, numBytes)
random.Read(balanceBytes) random.Read(balanceBytes)
balance := new(uint256.Int).SetBytes(balanceBytes) balance := new(uint256.Int).SetBytes(balanceBytes)
data, _ := rlp.EncodeToBytes(&types.StateAccount{Nonce: nonce, Balance: balance, Root: root, CodeHash: code}) data, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: nonce,
Balance: balance,
Root: root,
CodeHash: code,
})
accounts[i] = data accounts[i] = data
} }
return addresses, accounts return addresses, accounts
@ -856,6 +862,7 @@ func (s *spongeDb) Flush() {
s.sponge.Write([]byte(key)) s.sponge.Write([]byte(key))
s.sponge.Write([]byte(s.values[key])) s.sponge.Write([]byte(s.values[key]))
} }
fmt.Println(len(s.keys))
} }
// spongeBatch is a dummy batch which immediately writes to the underlying spongedb // spongeBatch is a dummy batch which immediately writes to the underlying spongedb
@ -873,10 +880,12 @@ func (b *spongeBatch) Write() error { return nil }
func (b *spongeBatch) Reset() {} func (b *spongeBatch) Reset() {}
func (b *spongeBatch) Replay(w ethdb.KeyValueWriter) error { return nil } func (b *spongeBatch) Replay(w ethdb.KeyValueWriter) error { return nil }
// TestCommitSequence tests that the trie.Commit operation writes the elements of the trie // TestCommitSequence tests that the trie.Commit operation writes the elements
// in the expected order. // of the trie in the expected order.
// The test data was based on the 'master' code, and is basically random. It can be used //
// to check whether changes to the trie modifies the write order or data in any way. // The test data was based on the 'master' code, and is basically random.
// It can be used to check whether changes to the trie modifies the write order
// or data in any way.
func TestCommitSequence(t *testing.T) { func TestCommitSequence(t *testing.T) {
for i, tc := range []struct { for i, tc := range []struct {
count int count int
@ -887,19 +896,23 @@ func TestCommitSequence(t *testing.T) {
{2000, common.FromHex("4574cd8e6b17f3fe8ad89140d1d0bf4f1bd7a87a8ac3fb623b33550544c77635")}, {2000, common.FromHex("4574cd8e6b17f3fe8ad89140d1d0bf4f1bd7a87a8ac3fb623b33550544c77635")},
} { } {
addresses, accounts := makeAccounts(tc.count) addresses, accounts := makeAccounts(tc.count)
// This spongeDb is used to check the sequence of disk-db-writes // This spongeDb is used to check the sequence of disk-db-writes
s := &spongeDb{sponge: crypto.NewKeccakState()} s := &spongeDb{sponge: crypto.NewKeccakState()}
db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme)
trie := NewEmpty(db)
// Fill the trie with elements // Fill the trie with elements
trie := NewEmpty(db)
for i := 0; i < tc.count; i++ { for i := 0; i < tc.count; i++ {
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i]) trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
} }
// Flush trie -> database // Flush trie -> database
root, nodes := trie.Commit(false) root, nodes := trie.Commit(false)
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
// Flush memdb -> disk (sponge) // Flush memdb -> disk (sponge)
db.Commit(root) db.Commit(root)
if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) {
t.Errorf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp) t.Errorf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp)
} }
@ -917,12 +930,13 @@ func TestCommitSequenceRandomBlobs(t *testing.T) {
{200, common.FromHex("dde92ca9812e068e6982d04b40846dc65a61a9fd4996fc0f55f2fde172a8e13c")}, {200, common.FromHex("dde92ca9812e068e6982d04b40846dc65a61a9fd4996fc0f55f2fde172a8e13c")},
{2000, common.FromHex("ab553a7f9aff82e3929c382908e30ef7dd17a332933e92ba3fe873fc661ef382")}, {2000, common.FromHex("ab553a7f9aff82e3929c382908e30ef7dd17a332933e92ba3fe873fc661ef382")},
} { } {
prng := rand.New(rand.NewSource(int64(i)))
// This spongeDb is used to check the sequence of disk-db-writes // This spongeDb is used to check the sequence of disk-db-writes
prng := rand.New(rand.NewSource(int64(i)))
s := &spongeDb{sponge: crypto.NewKeccakState()} s := &spongeDb{sponge: crypto.NewKeccakState()}
db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme)
trie := NewEmpty(db)
// Fill the trie with elements // Fill the trie with elements
trie := NewEmpty(db)
for i := 0; i < tc.count; i++ { for i := 0; i < tc.count; i++ {
key := make([]byte, 32) key := make([]byte, 32)
var val []byte var val []byte
@ -939,6 +953,7 @@ func TestCommitSequenceRandomBlobs(t *testing.T) {
// Flush trie -> database // Flush trie -> database
root, nodes := trie.Commit(false) root, nodes := trie.Commit(false)
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
// Flush memdb -> disk (sponge) // Flush memdb -> disk (sponge)
db.Commit(root) db.Commit(root)
if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) { if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) {
@ -974,19 +989,22 @@ func TestCommitSequenceStackTrie(t *testing.T) {
// For the stack trie, we need to do inserts in proper order // For the stack trie, we need to do inserts in proper order
key := make([]byte, 32) key := make([]byte, 32)
binary.BigEndian.PutUint64(key, uint64(i)) binary.BigEndian.PutUint64(key, uint64(i))
var val []byte
// 50% short elements, 50% large elements // 50% short elements, 50% large elements
var val []byte
if prng.Intn(2) == 0 { if prng.Intn(2) == 0 {
val = make([]byte, 1+prng.Intn(32)) val = make([]byte, 1+prng.Intn(32))
} else { } else {
val = make([]byte, 1+prng.Intn(1024)) val = make([]byte, 1+prng.Intn(1024))
} }
prng.Read(val) prng.Read(val)
trie.Update(key, val) trie.Update(key, val)
stTrie.Update(key, val) stTrie.Update(key, val)
} }
// Flush trie -> database // Flush trie -> database
root, nodes := trie.Commit(false) root, nodes := trie.Commit(false)
// Flush memdb -> disk (sponge) // Flush memdb -> disk (sponge)
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
db.Commit(root) db.Commit(root)
@ -1045,6 +1063,7 @@ func TestCommitSequenceSmallRoot(t *testing.T) {
// Flush trie -> database // Flush trie -> database
root, nodes := trie.Commit(false) root, nodes := trie.Commit(false)
// Flush memdb -> disk (sponge) // Flush memdb -> disk (sponge)
db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)) db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
db.Commit(root) db.Commit(root)

View File

@ -19,6 +19,6 @@ package version
const ( const (
Major = 1 // Major version component of the current release Major = 1 // Major version component of the current release
Minor = 15 // Minor version component of the current release Minor = 15 // Minor version component of the current release
Patch = 1 // Patch version component of the current release Patch = 3 // Patch version component of the current release
Meta = "unstable" // Version metadata to append to the version string Meta = "unstable" // Version metadata to append to the version string
) )