Compare commits
4 Commits
a1093d98eb
...
v1.14.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c350d3acd5 | ||
|
|
a9523b6428 | ||
|
|
aa55f5ea20 | ||
|
|
aadddf3a6e |
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -20,6 +20,5 @@ les/ @zsfelfoldi @rjl493456442
|
|||||||
light/ @zsfelfoldi @rjl493456442
|
light/ @zsfelfoldi @rjl493456442
|
||||||
node/ @fjl
|
node/ @fjl
|
||||||
p2p/ @fjl @zsfelfoldi
|
p2p/ @fjl @zsfelfoldi
|
||||||
params/ @fjl @holiman @karalabe @gballet @rjl493456442 @zsfelfoldi
|
|
||||||
rpc/ @fjl @holiman
|
rpc/ @fjl @holiman
|
||||||
signer/ @holiman
|
signer/ @holiman
|
||||||
|
|||||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -4,11 +4,16 @@
|
|||||||
# or operating system, you probably want to add a global ignore instead:
|
# or operating system, you probably want to add a global ignore instead:
|
||||||
# git config --global core.excludesfile ~/.gitignore_global
|
# git config --global core.excludesfile ~/.gitignore_global
|
||||||
|
|
||||||
|
/tmp
|
||||||
*/**/*un~
|
*/**/*un~
|
||||||
*/**/*.test
|
*/**/*.test
|
||||||
*un~
|
*un~
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*/**/.DS_Store
|
*/**/.DS_Store
|
||||||
|
.ethtest
|
||||||
|
*/**/*tx_database*
|
||||||
|
*/**/*dapps*
|
||||||
|
build/_vendor/pkg
|
||||||
|
|
||||||
#*
|
#*
|
||||||
.#*
|
.#*
|
||||||
@@ -41,4 +46,15 @@ profile.cov
|
|||||||
# VS Code
|
# VS Code
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
# dashboard
|
||||||
|
/dashboard/assets/flow-typed
|
||||||
|
/dashboard/assets/node_modules
|
||||||
|
/dashboard/assets/stats.json
|
||||||
|
/dashboard/assets/bundle.js
|
||||||
|
/dashboard/assets/bundle.js.map
|
||||||
|
/dashboard/assets/package-lock.json
|
||||||
|
|
||||||
|
**/yarn-error.log
|
||||||
|
logs/
|
||||||
|
|
||||||
tests/spec-tests/
|
tests/spec-tests/
|
||||||
|
|||||||
@@ -21,14 +21,10 @@ linters:
|
|||||||
- staticcheck
|
- staticcheck
|
||||||
- bidichk
|
- bidichk
|
||||||
- durationcheck
|
- durationcheck
|
||||||
- copyloopvar
|
- exportloopref
|
||||||
- whitespace
|
- whitespace
|
||||||
- revive # only certain checks enabled
|
- revive # only certain checks enabled
|
||||||
- durationcheck
|
|
||||||
- gocheckcompilerdirectives
|
|
||||||
- reassign
|
|
||||||
- mirror
|
|
||||||
- tenv
|
|
||||||
### linters we tried and will not be using:
|
### linters we tried and will not be using:
|
||||||
###
|
###
|
||||||
# - structcheck # lots of false positives
|
# - structcheck # lots of false positives
|
||||||
|
|||||||
25
.travis.yml
25
.travis.yml
@@ -9,7 +9,8 @@ jobs:
|
|||||||
- azure-osx
|
- azure-osx
|
||||||
|
|
||||||
include:
|
include:
|
||||||
# This builder create and push the Docker images for all architectures
|
# These builders create the Docker sub-images for multi-arch push and each
|
||||||
|
# will attempt to push the multi-arch image if they are the last builder
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = push
|
if: type = push
|
||||||
os: linux
|
os: linux
|
||||||
@@ -25,7 +26,24 @@ jobs:
|
|||||||
before_install:
|
before_install:
|
||||||
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
script:
|
script:
|
||||||
- go run build/ci.go dockerx -platform "linux/amd64,linux/arm64" -upload ethereum/client-go
|
- go run build/ci.go docker -image -manifest amd64,arm64 -upload ethereum/client-go
|
||||||
|
|
||||||
|
- stage: build
|
||||||
|
if: type = push
|
||||||
|
os: linux
|
||||||
|
arch: arm64
|
||||||
|
dist: focal
|
||||||
|
go: 1.23.x
|
||||||
|
env:
|
||||||
|
- docker
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
git:
|
||||||
|
submodules: false # avoid cloning ethereum/tests
|
||||||
|
before_install:
|
||||||
|
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
|
script:
|
||||||
|
- go run build/ci.go docker -image -manifest amd64,arm64 -upload ethereum/client-go
|
||||||
|
|
||||||
# This builder does the Linux Azure uploads
|
# This builder does the Linux Azure uploads
|
||||||
- stage: build
|
- stage: build
|
||||||
@@ -67,13 +85,12 @@ jobs:
|
|||||||
if: type = push
|
if: type = push
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode14.2
|
osx_image: xcode14.2
|
||||||
go: 1.23.1 # See https://github.com/ethereum/go-ethereum/pull/30478
|
go: 1.23.x
|
||||||
env:
|
env:
|
||||||
- azure-osx
|
- azure-osx
|
||||||
git:
|
git:
|
||||||
submodules: false # avoid cloning ethereum/tests
|
submodules: false # avoid cloning ethereum/tests
|
||||||
script:
|
script:
|
||||||
- ln -sf /Users/travis/gopath/bin/go1.23.1 /usr/local/bin/go # Work around travis go-setup bug
|
|
||||||
- go run build/ci.go install -dlgo
|
- go run build/ci.go install -dlgo
|
||||||
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
||||||
- go run build/ci.go install -dlgo -arch arm64
|
- go run build/ci.go install -dlgo -arch arm64
|
||||||
|
|||||||
@@ -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.23-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
|
||||||
|
|
||||||
|
|||||||
@@ -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.23-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
|
||||||
|
|
||||||
@@ -14,13 +14,6 @@ COPY go.sum /go-ethereum/
|
|||||||
RUN cd /go-ethereum && go mod download
|
RUN cd /go-ethereum && go mod download
|
||||||
|
|
||||||
ADD . /go-ethereum
|
ADD . /go-ethereum
|
||||||
|
|
||||||
# This is not strictly necessary, but it matches the "Dockerfile" steps, thus
|
|
||||||
# makes it so that under certain circumstances, the docker layer can be cached,
|
|
||||||
# and the builder can jump to the next (build all) command, with the go cache fully loaded.
|
|
||||||
#
|
|
||||||
RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
|
|
||||||
|
|
||||||
RUN cd /go-ethereum && go run build/ci.go install -static
|
RUN cd /go-ethereum && go run build/ci.go install -static
|
||||||
|
|
||||||
# Pull all binaries into a second stage deploy alpine container
|
# Pull all binaries into a second stage deploy alpine container
|
||||||
|
|||||||
204
SECURITY.md
204
SECURITY.md
@@ -29,69 +29,147 @@ Fingerprint: `AE96 ED96 9E47 9B00 84F3 E17F E88D 3334 FA5F 6A0A`
|
|||||||
|
|
||||||
```
|
```
|
||||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
Version: SKS 1.1.6
|
||||||
|
Comment: Hostname: pgp.mit.edu
|
||||||
|
|
||||||
mQINBFgl3tgBEAC8A1tUBkD9YV+eLrOmtgy+/JS/H9RoZvkg3K1WZ8IYfj6iIRaY
|
mQINBFgl3tgBEAC8A1tUBkD9YV+eLrOmtgy+/JS/H9RoZvkg3K1WZ8IYfj6iIRaYneAk3Bp1
|
||||||
neAk3Bp182GUPVz/zhKr2g0tMXIScDR3EnaDsY+Qg+JqQl8NOG+Cikr1nnkG2on9
|
82GUPVz/zhKr2g0tMXIScDR3EnaDsY+Qg+JqQl8NOG+Cikr1nnkG2on9L8c8yiqry1ZTCmYM
|
||||||
L8c8yiqry1ZTCmYMqCa2acTFqnyuXJ482aZNtB4QG2BpzfhW4k8YThpegk/EoRUi
|
qCa2acTFqnyuXJ482aZNtB4QG2BpzfhW4k8YThpegk/EoRUim+y7buJDtoNf7YILlhDQXN8q
|
||||||
m+y7buJDtoNf7YILlhDQXN8qlHB02DWOVUihph9tUIFsPK6BvTr9SIr/eG6j6k0b
|
lHB02DWOVUihph9tUIFsPK6BvTr9SIr/eG6j6k0bfUo9pexOn7LS4SojoJmsm/5dp6AoKlac
|
||||||
fUo9pexOn7LS4SojoJmsm/5dp6AoKlac48cZU5zwR9AYcq/nvkrfmf2WkObg/xRd
|
48cZU5zwR9AYcq/nvkrfmf2WkObg/xRdEvKZzn05jRopmAIwmoC3CiLmqCHPmT5a29vEob/y
|
||||||
EvKZzn05jRopmAIwmoC3CiLmqCHPmT5a29vEob/yPFE335k+ujjZCPOu7OwjzDk7
|
PFE335k+ujjZCPOu7OwjzDk7M0zMSfnNfDq8bXh16nn+ueBxJ0NzgD1oC6c2PhM+XRQCXCho
|
||||||
M0zMSfnNfDq8bXh16nn+ueBxJ0NzgD1oC6c2PhM+XRQCXChoyI8vbfp4dGvCvYqv
|
yI8vbfp4dGvCvYqvQAE1bWjqnumZ/7vUPgZN6gDfiAzG2mUxC2SeFBhacgzDvtQls+uuvm+F
|
||||||
QAE1bWjqnumZ/7vUPgZN6gDfiAzG2mUxC2SeFBhacgzDvtQls+uuvm+FnQOUgg2H
|
nQOUgg2Hh8x2zgoZ7kqV29wjaUPFREuew7e+Th5BxielnzOfVycVXeSuvvIn6cd3g/s8mX1c
|
||||||
h8x2zgoZ7kqV29wjaUPFREuew7e+Th5BxielnzOfVycVXeSuvvIn6cd3g/s8mX1c
|
2kLSXJR7+KdWDrIrR5Az0kwAqFZt6B6QTlDrPswu3mxsm5TzMbny0PsbL/HBM+GZEZCjMXxB
|
||||||
2kLSXJR7+KdWDrIrR5Az0kwAqFZt6B6QTlDrPswu3mxsm5TzMbny0PsbL/HBM+GZ
|
8bqV2eSaktjnSlUNX1VXxyOxXA+ZG2jwpr51egi57riVRXokrQARAQABtDRFdGhlcmV1bSBG
|
||||||
EZCjMXxB8bqV2eSaktjnSlUNX1VXxyOxXA+ZG2jwpr51egi57riVRXokrQARAQAB
|
b3VuZGF0aW9uIEJ1ZyBCb3VudHkgPGJvdW50eUBldGhlcmV1bS5vcmc+iQIcBBEBCAAGBQJa
|
||||||
tDRFdGhlcmV1bSBGb3VuZGF0aW9uIEJ1ZyBCb3VudHkgPGJvdW50eUBldGhlcmV1
|
FCY6AAoJEHoMA3Q0/nfveH8P+gJBPo9BXZL8isUfbUWjwLi81Yi70hZqIJUnz64SWTqBzg5b
|
||||||
bS5vcmc+iQJVBBMBCAA/AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgBYhBK6W
|
mCZ69Ji5637THsxQetS2ARabz0DybQ779FhD/IWnqV9T3KuBM/9RzJtuhLzKCyMrAINPMo28
|
||||||
7ZaeR5sAhPPhf+iNMzT6X2oKBQJl2LD9BQkRdTklAAoJEOiNMzT6X2oKYYYQALkV
|
rKWdunHHarpuR4m3tL2zWJkle5QVYb+vkZXJJE98PJw+N4IYeKKeCs2ubeqZu636GA0sMzzB
|
||||||
wJjWYoVoMuw9D1ybQo4Sqyp6D/XYHXSpqZDO9RlADQisYBfuO7EW75evgZ+54Ajc
|
Jn3m/dRRA2va+/zzbr6F6b51ynzbMxWKTsJnstjC8gs8EeI+Zcd6otSyelLtCUkk3h5sTvpV
|
||||||
8gZ2BUkFcSR9z2t0TEkUyjmPDZsaElTTP2Boa2GG5pyziEM6t1cMMY1sP1aotx9H
|
Wv67BNSU0BYsMkxyFi9PUyy07Wixgeas89K5jG1oOtDva/FkpRHrTE/WA5OXDRcLrHJM+SwD
|
||||||
DYwCeMmDv0wTMi6v0C6+/in2hBxbGALRbQKWKd/5ss4OEPe37hG9zAJcBYZg2tes
|
CwqcLQqJd09NxwUW1iKeBmPptTiOGu1Gv2o7aEyoaWrHRBO7JuYrQrj6q2B3H1Je0zjAd2qt
|
||||||
O7ceg7LHZpNC1zvMUrBY6os74FJ437f8bankqvVE83/dvTcCDhMsei9LiWS2uo26
|
09ni2bLwLn4LA+VDpprNTO+eZDprv09s2oFSU6NwziHybovu0y7X4pADGkK2evOM7c86PohX
|
||||||
qiyqeR9lZEj8W5F6UgkQH+UOhamJ9UB3N/h//ipKrwtiv0+jQm9oNG7aIAi3UJgD
|
QRQ1M1T16xLj6wP8/Ykwl6v/LUk7iDPXP3GPILnh4YOkwBR3DsCOPn8098xy7FxEELmupRzt
|
||||||
CvSod87H0l7/U8RWzyam/r8eh4KFM75hIVtqEy5jFV2z7x2SibXQi7WRfAysjFLp
|
Cj9oC7YAoweeShgUjBPzb+nGY1m6OcFfbUPBgFyMMfwF6joHbiVIO+39+Ut2g2ysZa7KF+yp
|
||||||
/li8ff6kLDR9IMATuMSF7Ol0O9JMRfSPjRZRtVOwYVIBla3BhfMrjvMMcZMAy/qS
|
XqVDqyEkYXsOLb25OC7brt8IJEPgBPwcHK5GNag6RfLxnQV+iVZ9KNH1yQgSiQI+BBMBAgAo
|
||||||
DWx2iFYDMGsswv7hp3lsFOaa1ju95ClZZk3q/z7u5gH7LFAxR0jPaW48ay3CFylW
|
AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAUCWglh+gUJBaNgWAAKCRDojTM0+l9qCgQ2
|
||||||
sDpQpO1DWb9uXBdhOU+MN18uSjqzocga3Wz2C8jhWRvxyFf3SNIybm3zk6W6IIoy
|
D/4udJpV4zGIZW1yNaVvtd3vfKsTLi7GIRJLUBqVb2Yx/uhnN8jTl/tAhCVosCQ1pzvi9kMl
|
||||||
6KmwSRZ30oxizy6zMYw1qJE89zjjumzlZAm0R/Q4Ui+WJhlSyrYbqzqdxYuLgdEL
|
s8qO1vu2kw5EWFFkwK96roI8pTql3VIjwhRVQrCkR7oAk/eUd1U/nt2q6J4UTYeVgqbq4dsI
|
||||||
lgKfbv9/t8tNXGGSuCe5L7quOv9k7l2+QmLlg+SJtDlFdGhlcmV1bSBGb3VuZGF0
|
ZZTRyPJMD667YpuAIcaah+w9j/E5xksYQdMeprnDrQkkBCb4FIMqfDzBPKvEa8DcQr949K85
|
||||||
aW9uIFNlY3VyaXR5IFRlYW0gPHNlY3VyaXR5QGV0aGVyZXVtLm9yZz6JAlUEEwEI
|
kxhr6LDq9i5l4Egxt2JdH8DaR4GLca6+oHy0MyPs/bZOsfmZUObfM2oZgPpqYM96JanhzO1j
|
||||||
AD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEErpbtlp5HmwCE8+F/6I0z
|
dpnItyBii2pc+kNx5nMOf4eikE/MBv+WUJ0TttWzApGGmFUzDhtuEvRH9NBjtJ/pMrYspIGu
|
||||||
NPpfagoFAmXYsP4FCRF1OSUACgkQ6I0zNPpfagoUGA/+LVzXUJrsfi8+ADMF1hru
|
O/QNY5KKOKQTvVIlwGcm8dTsSkqtBDSUwZyWbfKfKOI1/RhM9dC3gj5/BOY57DYYV4rdTK01
|
||||||
wFDcY1r+vM4Ovbk1NhCc/DnV5VG40j5FiQpE81BNiH59sYeZkQm9jFbwevK7Zpuq
|
ZtYjuhdfs2bhuP1uF/cgnSSZlv8azvf7Egh7tHPnYxvLjfq1bJAhCIX0hNg0a81/ndPAEFky
|
||||||
RZaG2WGiwU/11xrt5/Qjq7T+vEtd94546kFcBnP8uexZqP4dTi4LHa2on8aRbwzN
|
fSko+JPKvdSvsUcSi2QQ4U2HX//jNBjXRfG4F0utgbJnhXzEckz6gqt7wSDZH2oddVuO8Ssc
|
||||||
7RjCpCQhy1TUuk47dyOR1y3ZHrpTwkHpuhwgffaWtxgSyCMYz7fsd5Ukh3eE+Ani
|
T7sK+CdXthSKnRyuI+sGUpG+6glpKWIfYkWFKNZWuQ+YUatY3QEDHXTIioycSmV8p4d/g/0S
|
||||||
90CIUieve2U3o+WPxBD9PRaIPg6LmBhfGxGvC/6tqY9W3Z9xEOVDxC4wdYppQzsg
|
V6TegidLxY8bXMkbqz+3n6FArRffv5MH7qt3cYkCPgQTAQIAKAUCWCXhOwIbAwUJAeEzgAYL
|
||||||
Pg7bNnVmlFWHsEk8FuMfY8nTqY3/ojhJxikWKz2V3Y2AbsLEXCvrEg6b4FvmsS97
|
CQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ6I0zNPpfagrN/w/+Igp3vtYdNunikw3yHnYf
|
||||||
8ifEBbFXU8hvMSpMLtO7vLamWyOHq41IXWH6HLNLhDfDzTfpAJ8iYDKGj72YsMzF
|
Jkm0MmaMDUM9mtsaXVN6xb9n25N3Xa3GWCpmdsbYZ8334tI/oQ4/NHq/bEI5WFH5F1aFkMkm
|
||||||
0fIjPa6mniMB2RmREAM0Jas3M/6DUw1EzwK1iQofIBoCRPIkR5mxmzjcRB6tVdQa
|
5AJVLuUkipCtmCZ5NkbRPJA9l0uNUUE6uuFXBhf4ddu7jb0jMetRF/kifJHVCCo5fISUNhLp
|
||||||
on20/9YTKKBUQAdK0OWW8j1euuULDgNdkN2LBXdQLy/JcQiggU8kOCKL/Lmj5HWP
|
7bwcWq9qgDQNZNYMOo4s9WX5Tl+5x4gTZdd2/cAYt49h/wnkw+huM+Jm0GojpLqIQ1jZiffm
|
||||||
FNT9rYfnjmCuux3UfJGfhPryujEA0CdIfq1Qf4ldOVzpWYjsMn+yQxAQTorAzF3z
|
otf5rF4L+JhIIdW0W4IIh1v9BhHVllXw+z9oj0PALstT5h8/DuKoIiirFJ4DejU85GR1KKAS
|
||||||
iYddP2cw/Nvookay8xywKJnDsaRaWqdQ8Ceox3qSB4LCjQRNR5c3HfvGm3EBdEyI
|
DeO19G/lSpWj1rSgFv2N2gAOxq0X+BbQTua2jdcY6JpHR4H1JJ2wzfHsHPgDQcgY1rGlmjVF
|
||||||
zEEpjZ6GHa05DCajqKjtjlm5Ag0EWCXe2AEQAJuCrodM3mAQGLSWQP8xp8ieY2L7
|
aqU73WV4/hzXc/HshK/k4Zd8uD4zypv6rFsZ3UemK0aL2zXLVpV8SPWQ61nS03x675SmDlYr
|
||||||
n1TmBEZiqTjpaV9GOEe51eMOmAPSWiUZviFiie2QxopGUKDZG+CO+Tdm97Q8paMr
|
A80ENfdqvsn00JQuBVIv4Tv0Ub7NfDraDGJCst8rObjBT/0vnBWTBCebb2EsnS2iStIFkWdz
|
||||||
DuCvxgFr18wVjwGEBcjfY53Ij2sWHERkV9YB/ApWZPX0F14BBEW9x937zDx/VdVz
|
/WXs4L4Yzre1iJwqRjiuqahZR5jHsjAUf2a0O29HVHE7zlFtCFmLPClml2lGQfQOpm5klGZF
|
||||||
7N11QswkUFOv7EoOUhFbBOR0s9B5ZuOjR4eX+Di24uIutPFVuePbpt/7b7UNsz/D
|
rmvus+qZ9rt35UgWHPZezykkwtWrFOwspwuCWaPDto6tgbRJZ4ftitpdYYM3dKW9IGJXBwrt
|
||||||
lVq/M+uS+Ieq8p79A/+BrLhANWJa8WAtv3SJ18Ach2w+B+WnRUNLmtUcUvoPvetJ
|
BQrMsu+lp0vDF+yJAlUEEwEIAD8CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAFiEErpbt
|
||||||
F0hGjcjxzyZig2NJHhcO6+A6QApb0tHem+i4UceOnoWvQZ6xFuttvYQbrqI+xH30
|
lp5HmwCE8+F/6I0zNPpfagoFAmEAEJwFCQycmLgACgkQ6I0zNPpfagpWoBAAhOcbMAUw6Zt0
|
||||||
xDsWogv1Uwc+baa1H5e9ucqQfatjISpoxtJ2Tb2MZqmQBaV7iwiFIqTvj0Di0aQe
|
GYzT3sR5/c0iatezPzXEXJf9ebzR8M5uPElXcxcnMx1dvXZmGPXPJKCPa99WCu1NZYy8F+Wj
|
||||||
XTwpnY32joat9R6E/9XZ4ktqmHYOKgUvUfFGvKsrLzRBAoswlF6TGKCryCt5bzEH
|
GTOY9tfIkvSxhys1p/giPAmvid6uQmD+bz7ivktnyzCkDWfMA+l8lsCSEqVlaq6y5T+a6SWB
|
||||||
jO5/0yS6i75Ec2ajw95seMWy0uKCIPr/M/Z77i1SatPT8lMY5KGgYyXxG3RVHF08
|
6TzC2S0MPb/RrC/7DpwyrNYWumvyVJh09adm1Mw/UGgst/sZ8eMaRYEd3X0yyT1CBpX4zp2E
|
||||||
iYq6f7gs5dt87ECs5KRjqLfn6CyCSRLLWBMkTQFjdL1q5Pr5iuCVj9NY9D0gnFZU
|
qQj9IEOTizvzv1x2jkHe5ZUeU3+nTBNlhSA+WFHUi0pfBdo2qog3Mv2EC1P2qMKoSdD5tPbA
|
||||||
4qVP7dYinnAm7ZsEpDjbRUuoNjOShbK16X9szUAJS2KkyIhV5Sza4WJGOnMDVbLR
|
zql1yKoHHnXOMsqdftGwbiv2sYXWvrYvmaCd3Ys/viOyt3HOy9uV2ZEtBd9Yqo9x/NZj8QMA
|
||||||
Aco9N1K4aUk9Gt9xABEBAAGJAjwEGAEIACYCGwwWIQSulu2WnkebAITz4X/ojTM0
|
nY5k8jjrIXbUC89MqrJsQ6xxWQIg5ikMT7DvY0Ln89ev4oJyVvwIQAwCm4jUzFNm9bZLYDOP
|
||||||
+l9qCgUCZdiwoAUJEXU4yAAKCRDojTM0+l9qCj2PD/9pbIPRMZtvKIIE+OhOAl/s
|
5lGJCV7tF5NYVU7NxNM8vescKc40mVNK/pygS5mxhK9QYOUjZsIv8gddrl1TkqrFMuxFnTyN
|
||||||
qfZJXByAM40ELpUhDHqwbOplIEyvXtWfQ5c+kWlG/LPJ2CgLkHyFQDn6tuat82rH
|
WvzE29wFu/n4N1DkF+ZBqS70SlRvB+Hjz5LrDgEzF1Wf1eA/wq1dZbvMjjDVIc2VGlYp8Cp2
|
||||||
/5VoZyxp16CBAwEgYdycOr9hMGSVKNIJDfV9Bu6VtZnn6fa/swBzGE7eVpXsIoNr
|
8ob23c1seTtYXTNYgSR5go4EpH+xi+bIWv01bQQ9xGwBbT5sm4WUeWOcmX4QewzLZ3T/wK9+
|
||||||
jeqsogBtzLecG1oHMXRMq7oUqu9c6VNoCx2uxRUOeWW8YuP7h9j6mxIuKKbcpmQ5
|
N4Ye/hmU9O34FwWJOY58EIe0OUV0aGVyZXVtIEZvdW5kYXRpb24gU2VjdXJpdHkgVGVhbSA8
|
||||||
RSLNEhJZJsMMFLf8RAQPXmshG1ZixY2ZliNe/TTm6eEfFCw0KcQxoX9LmurLWE9w
|
c2VjdXJpdHlAZXRoZXJldW0ub3JnPokCHAQRAQgABgUCWhQmOgAKCRB6DAN0NP5372LSEACT
|
||||||
dIKgn1/nQ04GFnmtcq3hVxY/m9BvzY1jmZXNd4TdpfrPXhi0W/GDn53ERFPJmw5L
|
wZk1TASWZj5QF7rmkIM1GEyBxLE+PundNcMgM9Ktj1315ED8SmiukNI4knVS1MY99OIgXhQl
|
||||||
F8ogxzD/ekxzyd9nCCgtzkamtBKDJk35x/MoVWMLjD5k6P+yW7YY4xMQliSJHKss
|
D1foF2GKdTomrwwC4012zTNyUYCY60LnPZ6Z511HG+rZgZtZrbkz0IiUpwAlhGQND77lBqem
|
||||||
leLnaPpgDBi4KPtLxPswgFqObcy4TNse07rFO4AyHf11FBwMTEfuODCOMnQTpi3z
|
J3K+CFX2XpDA/ojui/kqrY4cwMT5P8xPJkwgpRgw/jgdcZyJTsXdHblV9IGU4H1Vd1SgcfAf
|
||||||
Zx6KxvS3BEY36abjvwrqsmt8dJ/+/QXT0e82fo2kJ65sXIszez3e0VUZ8KrMp+wd
|
Db3YxDUlBtzlp0NkZqxen8irLIXUQvsfuIfRUbUSkWoK/n3U/gOCajAe8ZNF07iX4OWjH4Sw
|
||||||
X0GWYWAfqXws6HrQFYfIpEE0Vz9gXDxEOTFZ2FoVIvIHyRfyDrAIz3wZLmnLGk1h
|
NDA841WhFWcGE+d8+pfMVfPASU3UPKH72uw86b2VgR46Av6voyMFd1pj+yCA+YAhJuOpV4yL
|
||||||
l3CDjHF0Wigv0CacIQ1V1aYp3NhIVwAvShQ+qS5nFgik6UZnjjWibobOm3yQDzll
|
QaGg2Z0kVOjuNWK/kBzp1F58DWGh4YBatbhE/UyQOqAAtR7lNf0M3QF9AdrHTxX8oZeqVW3V
|
||||||
6F7hEeTW+gnXEI2gPjfb5w==
|
Fmi2mk0NwCIUv8SSrZr1dTchp04OtyXe5gZBXSfzncCSRQIUDC8OgNWaOzAaUmK299v4bvye
|
||||||
=b5eA
|
uSCxOysxC7Q1hZtjzFPKdljS81mRlYeUL4fHlJU9R57bg8mriSXLmn7eKrSEDm/EG5T8nRx7
|
||||||
|
TgX2MqJs8sWFxD2+bboVEu75yuFmZ//nmCBApAit9Hr2/sCshGIEpa9MQ6xJCYUxyqeJH+Cc
|
||||||
|
Aja0UfXhnK2uvPClpJLIl4RE3gm4OXeE1IkCPgQTAQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYC
|
||||||
|
AwECHgECF4AFAloJYfoFCQWjYFgACgkQ6I0zNPpfagr4MQ//cfp3GSbSG8dkqgctW67Fy7cQ
|
||||||
|
diiTmx3cwxY+tlI3yrNmdjtrIQMzGdqtY6LNz7aN87F8mXNf+DyVHX9+wd1Y8U+E+hVCTzKC
|
||||||
|
sefUfxTz6unD9TTcGqaoelgIPMn4IiKz1RZE6eKpfDWe6q78W1Y6x1bE0qGNSjqT/QSxpezF
|
||||||
|
E/OAm/t8RRxVxDtqz8LfH2zLea5zaC+ADj8EqgY9vX9TQa4DyVV8MgOyECCCadJQCD5O5hIA
|
||||||
|
B2gVDWwrAUw+KBwskXZ7Iq4reJTKLEmt5z9zgtJ/fABwaCFt66ojwg0/RjbO9cNA3ZwHLGwU
|
||||||
|
C6hkb6bRzIoZoMfYxVS84opiqf/Teq+t/XkBYCxbSXTJDA5MKjcVuw3N6YKWbkGP/EfQThe7
|
||||||
|
BfAKFwwIw5YmsWjHK8IQj6R6hBxzTz9rz8y1Lu8EAAFfA7OJKaboI2qbOlauH98OuOUmVtr1
|
||||||
|
TczHO+pTcgWVN0ytq2/pX5KBf4vbmULNbg3HFRq+gHx8CW+jyXGkcqjbgU/5FwtDxeqRTdGJ
|
||||||
|
SyBGNBEU6pBNolyynyaKaaJjJ/biY27pvjymL5rlz95BH3Dn16Z4RRmqwlT6eq/wFYginujg
|
||||||
|
CCE1icqOSE+Vjl7V8tV8AcgANkXKdbBE+Q8wlKsGI/kS1w4XFAYcaNHFT8qNeS8TSFXFhvU8
|
||||||
|
HylYxO79t56JAj4EEwECACgFAlgl3tgCGwMFCQHhM4AGCwkIBwMCBhUIAgkKCwQWAgMBAh4B
|
||||||
|
AheAAAoJEOiNMzT6X2oKmUMP/0hnaL6bVyepAq2LIdvIUbHfagt/Oo/KVfZs4bkM+xJOitJR
|
||||||
|
0kwZV9PTihXFdzhL/YNWc2+LtEBtKItqkJZKmWC0E6OPXGVuU6hfFPebuzVccYJfm0Q3Ej19
|
||||||
|
VJI9Uomf59Bpak8HYyEED7WVQjoYn7XVPsonwus/9+LDX+c5vutbrUdbjga3KjHbewD93X4O
|
||||||
|
wVVoXyHEmU2Plyg8qvzFbNDylCWO7N2McO6SN6+7DitGZGr2+jO+P2R4RT1cnl2V3IRVcWZ0
|
||||||
|
OTspPSnRGVr2fFiHN/+v8G/wHPLQcJZFvYPfUGNdcYbTmhWdiY0bEYXFiNrgzCCsyad7eKUR
|
||||||
|
WN9QmxqmyqLDjUEDJCAh19ES6Vg3tqGwXk+uNUCoF30ga0TxQt6UXZJDEQFAGeASQ/RqE/q1
|
||||||
|
EAuLv8IGM8o7IqKO2pWfLuqsY6dTbKBwDzz9YOJt7EOGuPPQbHxaYStTushZmJnm7hi8lhVG
|
||||||
|
jT7qsEJdE95Il+I/mHWnXsCevaXjZugBiyV9yvOq4Hwwe2s1zKfrnQ4u0cadvGAh2eIqum7M
|
||||||
|
Y3o6nD47aJ3YmEPX/WnhI56bACa2GmWvUwjI4c0/er3esSPYnuHnM9L8Am4qQwMVSmyU80tC
|
||||||
|
MI7A9e13Mvv+RRkYFLJ7PVPdNpbW5jqX1doklFpKf6/XM+B+ngYneU+zgCUBiQJVBBMBCAA/
|
||||||
|
AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgBYhBK6W7ZaeR5sAhPPhf+iNMzT6X2oKBQJh
|
||||||
|
ABCQBQkMnJi4AAoJEOiNMzT6X2oKAv0P+gJ3twBp5efNWyVLcIg4h4cOo9uD0NPvz8/fm2gX
|
||||||
|
FoOJL3MeigtPuSVfE9kuTaTuRbArzuFtdvH6G/kcRQvOlO4zyiIRHCk1gDHoIvvtn6RbRhVm
|
||||||
|
/Xo4uGIsFHst7n4A7BjicwEK5Op6Ih5Hoq19xz83YSBgBVk2fYEJIRyJiKFbyPjH0eSYe8v+
|
||||||
|
Ra5/F85ugLx1P6mMVkW+WPzULns89riW7BGTnZmXFHZp8nO2pkUlcI7F3KRG7l4kmlC50ox6
|
||||||
|
DiG/6AJCVulbAClky9C68TmJ/R1RazQxU/9IqVywsydq66tbJQbm5Z7GEti0C5jjbSRJL2oT
|
||||||
|
1xC7Rilr85PMREkPL3vegJdgj5PKlffZ/MocD/0EohiQ7wFpejFD4iTljeh0exRUwCRb6655
|
||||||
|
9ib34JSQgU8Hl4JJu+mEgd9v0ZHD0/1mMD6fnAR84zca+O3cdASbnQmzTOKcGzLIrkE8TEnU
|
||||||
|
+2UZ8Ol7SAAqmBgzY1gKOilUho6dkyCAwNL+QDpvrITDPLEFPsjyB/M2KudZSVEn+Rletju1
|
||||||
|
qkMW31qFMNlsbwzMZw+0USeGcs31Cs0B2/WQsro99CExlhS9auUFkmoVjJmYVTIYOM0zuPa4
|
||||||
|
OyGspqPhRu5hEsmMDPDWD7Aad5k4GTqogQNnuKyRliZjXXrDZqFD5nfsJSL8Ky/sJGEMuQIN
|
||||||
|
BFgl3tgBEACbgq6HTN5gEBi0lkD/MafInmNi+59U5gRGYqk46WlfRjhHudXjDpgD0lolGb4h
|
||||||
|
YontkMaKRlCg2Rvgjvk3Zve0PKWjKw7gr8YBa9fMFY8BhAXI32OdyI9rFhxEZFfWAfwKVmT1
|
||||||
|
9BdeAQRFvcfd+8w8f1XVc+zddULMJFBTr+xKDlIRWwTkdLPQeWbjo0eHl/g4tuLiLrTxVbnj
|
||||||
|
26bf+2+1DbM/w5VavzPrkviHqvKe/QP/gay4QDViWvFgLb90idfAHIdsPgflp0VDS5rVHFL6
|
||||||
|
D73rSRdIRo3I8c8mYoNjSR4XDuvgOkAKW9LR3pvouFHHjp6Fr0GesRbrbb2EG66iPsR99MQ7
|
||||||
|
FqIL9VMHPm2mtR+XvbnKkH2rYyEqaMbSdk29jGapkAWle4sIhSKk749A4tGkHl08KZ2N9o6G
|
||||||
|
rfUehP/V2eJLaph2DioFL1HxRryrKy80QQKLMJRekxigq8greW8xB4zuf9Mkuou+RHNmo8Pe
|
||||||
|
bHjFstLigiD6/zP2e+4tUmrT0/JTGOShoGMl8Rt0VRxdPImKun+4LOXbfOxArOSkY6i35+gs
|
||||||
|
gkkSy1gTJE0BY3S9auT6+YrglY/TWPQ9IJxWVOKlT+3WIp5wJu2bBKQ420VLqDYzkoWytel/
|
||||||
|
bM1ACUtipMiIVeUs2uFiRjpzA1Wy0QHKPTdSuGlJPRrfcQARAQABiQIlBBgBAgAPAhsMBQJa
|
||||||
|
CWIIBQkFo2BYAAoJEOiNMzT6X2oKgSwQAKKs7BGF8TyZeIEO2EUK7R2bdQDCdSGZY06tqLFg
|
||||||
|
3IHMGxDMb/7FVoa2AEsFgv6xpoebxBB5zkhUk7lslgxvKiSLYjxfNjTBltfiFJ+eQnf+OTs8
|
||||||
|
KeR51lLa66rvIH2qUzkNDCCTF45H4wIDpV05AXhBjKYkrDCrtey1rQyFp5fxI+0IQ1UKKXvz
|
||||||
|
ZK4GdxhxDbOUSd38MYy93nqcmclGSGK/gF8XiyuVjeifDCM6+T1NQTX0K9lneidcqtBDvlgg
|
||||||
|
JTLJtQPO33o5EHzXSiud+dKth1uUhZOFEaYRZoye1YE3yB0TNOOE8fXlvu8iuIAMBSDL9ep6
|
||||||
|
sEIaXYwoD60I2gHdWD0lkP0DOjGQpi4ouXM3Edsd5MTi0MDRNTij431kn8T/D0LCgmoUmYYM
|
||||||
|
BgbwFhXr67axPZlKjrqR0z3F/Elv0ZPPcVg1tNznsALYQ9Ovl6b5M3cJ5GapbbvNWC7yEE1q
|
||||||
|
Scl9HiMxjt/H6aPastH63/7wcN0TslW+zRBy05VNJvpWGStQXcngsSUeJtI1Gd992YNjUJq4
|
||||||
|
/Lih6Z1TlwcFVap+cTcDptoUvXYGg/9mRNNPZwErSfIJ0Ibnx9wPVuRN6NiCLOt2mtKp2F1p
|
||||||
|
M6AOQPpZ85vEh6I8i6OaO0w/Z0UHBwvpY6jDUliaROsWUQsqz78Z34CVj4cy6vPW2EF4iQIl
|
||||||
|
BBgBAgAPBQJYJd7YAhsMBQkB4TOAAAoJEOiNMzT6X2oKTjgP/1ojCVyGyvHMLUgnX0zwrR5Q
|
||||||
|
1M5RKFz6kHwKjODVLR3Isp8I935oTQt3DY7yFDI4t0GqbYRQMtxcNEb7maianhK2trCXfhPs
|
||||||
|
6/L04igjDf5iTcmzamXN6xnh5xkz06hZJJCMuu4MvKxC9MQHCVKAwjswl/9H9JqIBXAY3E2l
|
||||||
|
LpX5P+5jDZuPxS86p3+k4Rrdp9KTGXjiuEleM3zGlz5BLWydqovOck7C2aKh27ETFpDYY0z3
|
||||||
|
yQ5AsPJyk1rAr0wrH6+ywmwWlzuQewavnrLnJ2M8iMFXpIhyHeEIU/f7o8f+dQk72rZ9CGzd
|
||||||
|
cqig2za/BS3zawZWgbv2vB2elNsIllYLdir45jxBOxx2yvJvEuu4glz78y4oJTCTAYAbMlle
|
||||||
|
5gVdPkVcGyvvVS9tinnSaiIzuvWrYHKWll1uYPm2Q1CDs06P5I7bUGAXpgQLUh/XQguy/0sX
|
||||||
|
GWqW3FS5JzP+XgcR/7UASvwBdHylubKbeqEpB7G1s+m+8C67qOrc7EQv3Jmy1YDOkhEyNig1
|
||||||
|
rmjplLuir3tC1X+D7dHpn7NJe7nMwFx2b2MpMkLA9jPPAGPp/ekcu5sxCe+E0J/4UF++K+CR
|
||||||
|
XIxgtzU2UJfp8p9x+ygbx5qHinR0tVRdIzv3ZnGsXrfxnWfSOaB582cU3VRN9INzHHax8ETa
|
||||||
|
QVDnGO5uQa+FiQI8BBgBCAAmAhsMFiEErpbtlp5HmwCE8+F/6I0zNPpfagoFAmEAELYFCQyc
|
||||||
|
mN4ACgkQ6I0zNPpfagoqAQ/+MnDjBx8JWMd/XjeFoYKx/Oo0ntkInV+ME61JTBls4PdVk+TB
|
||||||
|
8PWZdPQHw9SnTvRmykFeznXIRzuxkowjrZYXdPXBxY2b1WyD5V3Ati1TM9vqpaR4osyPs2xy
|
||||||
|
I4dzDssh9YvUsIRL99O04/65lGiYeBNuACq+yK/7nD/ErzBkDYJHhMCdadbVWUACxvVIDvro
|
||||||
|
yQeVLKMsHqMCd8BTGD7VDs79NXskPnN77pAFnkzS4Z2b8SNzrlgTc5pUiuZHIXPIpEYmsYzh
|
||||||
|
ucTU6uI3dN1PbSFHK5tG2pHb4ZrPxY3L20Dgc2Tfu5/SDApZzwvvKTqjdO891MEJ++H+ssOz
|
||||||
|
i4O1UeWKs9owWttan9+PI47ozBSKOTxmMqLSQ0f56Np9FJsV0ilGxRKfjhzJ4KniOMUBA7mP
|
||||||
|
+m+TmXfVtthJred4sHlJMTJNpt+sCcT6wLMmyc3keIEAu33gsJj3LTpkEA2q+V+ZiP6Q8HRB
|
||||||
|
402ITklABSArrPSE/fQU9L8hZ5qmy0Z96z0iyILgVMLuRCCfQOMWhwl8yQWIIaf1yPI07xur
|
||||||
|
epy6lH7HmxjjOR7eo0DaSxQGQpThAtFGwkWkFh8yki8j3E42kkrxvEyyYZDXn2YcI3bpqhJx
|
||||||
|
PtwCMZUJ3kc/skOrs6bOI19iBNaEoNX5Dllm7UHjOgWNDQkcCuOCxucKano=
|
||||||
|
=arte
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1199,6 +1199,7 @@ func TestUnpackRevert(t *testing.T) {
|
|||||||
{"4e487b7100000000000000000000000000000000000000000000000000000000000000ff", "unknown panic code: 0xff", nil},
|
{"4e487b7100000000000000000000000000000000000000000000000000000000000000ff", "unknown panic code: 0xff", nil},
|
||||||
}
|
}
|
||||||
for index, c := range cases {
|
for index, c := range cases {
|
||||||
|
index, c := index, c
|
||||||
t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) {
|
t.Run(fmt.Sprintf("case %d", index), func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
got, err := UnpackRevert(common.Hex2Bytes(c.input))
|
got, err := UnpackRevert(common.Hex2Bytes(c.input))
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
|||||||
}
|
}
|
||||||
// Parse library references.
|
// Parse library references.
|
||||||
for pattern, name := range libs {
|
for pattern, name := range libs {
|
||||||
matched, err := regexp.MatchString("__\\$"+pattern+"\\$__", contracts[types[i]].InputBin)
|
matched, err := regexp.Match("__\\$"+pattern+"\\$__", []byte(contracts[types[i]].InputBin))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Could not search for pattern", "pattern", pattern, "contract", contracts[types[i]], "err", err)
|
log.Error("Could not search for pattern", "pattern", pattern, "contract", contracts[types[i]], "err", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -331,6 +331,7 @@ func TestEventTupleUnpack(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
tc := tc
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
err := unpackTestEventData(tc.dest, tc.data, tc.jsonLog, assert)
|
err := unpackTestEventData(tc.dest, tc.data, tc.jsonLog, assert)
|
||||||
if tc.error == "" {
|
if tc.error == "" {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import (
|
|||||||
func TestPack(t *testing.T) {
|
func TestPack(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
for i, test := range packUnpackTests {
|
for i, test := range packUnpackTests {
|
||||||
|
i, test := i, test
|
||||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
encb, err := hex.DecodeString(test.packed)
|
encb, err := hex.DecodeString(test.packed)
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ var reflectTests = []reflectTest{
|
|||||||
func TestReflectNameToStruct(t *testing.T) {
|
func TestReflectNameToStruct(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
for _, test := range reflectTests {
|
for _, test := range reflectTests {
|
||||||
|
test := test
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
m, err := mapArgNamesToStructFields(test.args, reflect.ValueOf(test.struc))
|
m, err := mapArgNamesToStructFields(test.args, reflect.ValueOf(test.struc))
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ func TestMakeTopics(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
got, err := MakeTopics(tt.args.query...)
|
got, err := MakeTopics(tt.args.query...)
|
||||||
@@ -372,6 +373,7 @@ func TestParseTopics(t *testing.T) {
|
|||||||
tests := setupTopicsTests()
|
tests := setupTopicsTests()
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
createObj := tt.args.createObj()
|
createObj := tt.args.createObj()
|
||||||
@@ -391,6 +393,7 @@ func TestParseTopicsIntoMap(t *testing.T) {
|
|||||||
tests := setupTopicsTests()
|
tests := setupTopicsTests()
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
outMap := make(map[string]interface{})
|
outMap := make(map[string]interface{})
|
||||||
|
|||||||
@@ -389,6 +389,7 @@ func TestMethodMultiReturn(t *testing.T) {
|
|||||||
"Can not unpack into a slice with wrong types",
|
"Can not unpack into a slice with wrong types",
|
||||||
}}
|
}}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
tc := tc
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
err := abi.UnpackIntoInterface(tc.dest, "multi", data)
|
err := abi.UnpackIntoInterface(tc.dest, "multi", data)
|
||||||
@@ -946,7 +947,7 @@ func TestOOMMaliciousInput(t *testing.T) {
|
|||||||
}
|
}
|
||||||
encb, err := hex.DecodeString(test.enc)
|
encb, err := hex.DecodeString(test.enc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("invalid hex: %s", test.enc)
|
t.Fatalf("invalid hex: %s" + test.enc)
|
||||||
}
|
}
|
||||||
_, err = abi.Methods["method"].Outputs.UnpackValues(encb)
|
_, err = abi.Methods["method"].Outputs.UnpackValues(encb)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ for:
|
|||||||
- image: Ubuntu
|
- image: Ubuntu
|
||||||
build_script:
|
build_script:
|
||||||
- go run build/ci.go lint
|
- go run build/ci.go lint
|
||||||
- go run build/ci.go check_tidy
|
- go run build/ci.go generate -verify
|
||||||
- go run build/ci.go check_generate
|
|
||||||
- go run build/ci.go check_baddeps
|
|
||||||
- go run build/ci.go install -dlgo
|
- go run build/ci.go install -dlgo
|
||||||
test_script:
|
test_script:
|
||||||
- go run build/ci.go test -dlgo -short
|
- go run build/ci.go test -dlgo -short
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ var (
|
|||||||
AddFork("BELLATRIX", 144896, []byte{2, 0, 0, 0}).
|
AddFork("BELLATRIX", 144896, []byte{2, 0, 0, 0}).
|
||||||
AddFork("CAPELLA", 194048, []byte{3, 0, 0, 0}).
|
AddFork("CAPELLA", 194048, []byte{3, 0, 0, 0}).
|
||||||
AddFork("DENEB", 269568, []byte{4, 0, 0, 0}),
|
AddFork("DENEB", 269568, []byte{4, 0, 0, 0}),
|
||||||
Checkpoint: common.HexToHash("0x6509b691f4de4f7b083f2784938fd52f0e131675432b3fd85ea549af9aebd3d0"),
|
Checkpoint: common.HexToHash("0x388be41594ec7d6a6894f18c73f3469f07e2c19a803de4755d335817ed8e2e5a"),
|
||||||
}
|
}
|
||||||
|
|
||||||
SepoliaConfig = lightClientConfig{
|
SepoliaConfig = lightClientConfig{
|
||||||
@@ -54,34 +54,19 @@ var (
|
|||||||
AddFork("BELLATRIX", 100, []byte{144, 0, 0, 113}).
|
AddFork("BELLATRIX", 100, []byte{144, 0, 0, 113}).
|
||||||
AddFork("CAPELLA", 56832, []byte{144, 0, 0, 114}).
|
AddFork("CAPELLA", 56832, []byte{144, 0, 0, 114}).
|
||||||
AddFork("DENEB", 132608, []byte{144, 0, 0, 115}),
|
AddFork("DENEB", 132608, []byte{144, 0, 0, 115}),
|
||||||
Checkpoint: common.HexToHash("0x456e85f5608afab3465a0580bff8572255f6d97af0c5f939e3f7536b5edb2d3f"),
|
Checkpoint: common.HexToHash("0x1005a6d9175e96bfbce4d35b80f468e9bff0b674e1e861d16e09e10005a58e81"),
|
||||||
}
|
|
||||||
|
|
||||||
HoleskyConfig = lightClientConfig{
|
|
||||||
ChainConfig: (&types.ChainConfig{
|
|
||||||
GenesisValidatorsRoot: common.HexToHash("0x9143aa7c615a7f7115e2b6aac319c03529df8242ae705fba9df39b79c59fa8b1"),
|
|
||||||
GenesisTime: 1695902400,
|
|
||||||
}).
|
|
||||||
AddFork("GENESIS", 0, []byte{1, 1, 112, 0}).
|
|
||||||
AddFork("ALTAIR", 0, []byte{2, 1, 112, 0}).
|
|
||||||
AddFork("BELLATRIX", 0, []byte{3, 1, 112, 0}).
|
|
||||||
AddFork("CAPELLA", 256, []byte{4, 1, 112, 0}).
|
|
||||||
AddFork("DENEB", 29696, []byte{5, 1, 112, 0}),
|
|
||||||
Checkpoint: common.HexToHash("0x6456a1317f54d4b4f2cb5bc9d153b5af0988fe767ef0609f0236cf29030bcff7"),
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeChainConfig(ctx *cli.Context) lightClientConfig {
|
func makeChainConfig(ctx *cli.Context) lightClientConfig {
|
||||||
var config lightClientConfig
|
var config lightClientConfig
|
||||||
customConfig := ctx.IsSet(utils.BeaconConfigFlag.Name)
|
customConfig := ctx.IsSet(utils.BeaconConfigFlag.Name)
|
||||||
utils.CheckExclusive(ctx, utils.MainnetFlag, utils.SepoliaFlag, utils.HoleskyFlag, utils.BeaconConfigFlag)
|
utils.CheckExclusive(ctx, utils.MainnetFlag, utils.SepoliaFlag, utils.BeaconConfigFlag)
|
||||||
switch {
|
switch {
|
||||||
case ctx.Bool(utils.MainnetFlag.Name):
|
case ctx.Bool(utils.MainnetFlag.Name):
|
||||||
config = MainnetConfig
|
config = MainnetConfig
|
||||||
case ctx.Bool(utils.SepoliaFlag.Name):
|
case ctx.Bool(utils.SepoliaFlag.Name):
|
||||||
config = SepoliaConfig
|
config = SepoliaConfig
|
||||||
case ctx.Bool(utils.HoleskyFlag.Name):
|
|
||||||
config = HoleskyConfig
|
|
||||||
default:
|
default:
|
||||||
if !customConfig {
|
if !customConfig {
|
||||||
config = MainnetConfig
|
config = MainnetConfig
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func (ec *engineClient) updateLoop(headCh <-chan types.ChainHeadEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent) (string, error) {
|
func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent) (string, error) {
|
||||||
execData := engine.BlockToExecutableData(event.Block, nil, nil, nil).ExecutionPayload
|
execData := engine.BlockToExecutableData(event.Block, nil, nil).ExecutionPayload
|
||||||
|
|
||||||
var (
|
var (
|
||||||
method string
|
method string
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
|||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||||
|
Deposits types.Deposits `json:"depositRequests"`
|
||||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
var enc ExecutableData
|
var enc ExecutableData
|
||||||
@@ -59,6 +60,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
|||||||
enc.Withdrawals = e.Withdrawals
|
enc.Withdrawals = e.Withdrawals
|
||||||
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
||||||
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
||||||
|
enc.Deposits = e.Deposits
|
||||||
enc.ExecutionWitness = e.ExecutionWitness
|
enc.ExecutionWitness = e.ExecutionWitness
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
@@ -83,6 +85,7 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
|||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||||
|
Deposits *types.Deposits `json:"depositRequests"`
|
||||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
var dec ExecutableData
|
var dec ExecutableData
|
||||||
@@ -157,6 +160,9 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
|||||||
if dec.ExcessBlobGas != nil {
|
if dec.ExcessBlobGas != nil {
|
||||||
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
||||||
}
|
}
|
||||||
|
if dec.Deposits != nil {
|
||||||
|
e.Deposits = *dec.Deposits
|
||||||
|
}
|
||||||
if dec.ExecutionWitness != nil {
|
if dec.ExecutionWitness != nil {
|
||||||
e.ExecutionWitness = dec.ExecutionWitness
|
e.ExecutionWitness = dec.ExecutionWitness
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,22 +18,13 @@ func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
|
|||||||
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
||||||
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
||||||
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
||||||
Requests []hexutil.Bytes `json:"executionRequests"`
|
|
||||||
Override bool `json:"shouldOverrideBuilder"`
|
Override bool `json:"shouldOverrideBuilder"`
|
||||||
Witness *hexutil.Bytes `json:"witness,omitempty"`
|
|
||||||
}
|
}
|
||||||
var enc ExecutionPayloadEnvelope
|
var enc ExecutionPayloadEnvelope
|
||||||
enc.ExecutionPayload = e.ExecutionPayload
|
enc.ExecutionPayload = e.ExecutionPayload
|
||||||
enc.BlockValue = (*hexutil.Big)(e.BlockValue)
|
enc.BlockValue = (*hexutil.Big)(e.BlockValue)
|
||||||
enc.BlobsBundle = e.BlobsBundle
|
enc.BlobsBundle = e.BlobsBundle
|
||||||
if e.Requests != nil {
|
|
||||||
enc.Requests = make([]hexutil.Bytes, len(e.Requests))
|
|
||||||
for k, v := range e.Requests {
|
|
||||||
enc.Requests[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enc.Override = e.Override
|
enc.Override = e.Override
|
||||||
enc.Witness = e.Witness
|
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,9 +34,7 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
|
|||||||
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
||||||
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
|
||||||
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
||||||
Requests []hexutil.Bytes `json:"executionRequests"`
|
|
||||||
Override *bool `json:"shouldOverrideBuilder"`
|
Override *bool `json:"shouldOverrideBuilder"`
|
||||||
Witness *hexutil.Bytes `json:"witness,omitempty"`
|
|
||||||
}
|
}
|
||||||
var dec ExecutionPayloadEnvelope
|
var dec ExecutionPayloadEnvelope
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
@@ -62,17 +51,8 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
|
|||||||
if dec.BlobsBundle != nil {
|
if dec.BlobsBundle != nil {
|
||||||
e.BlobsBundle = dec.BlobsBundle
|
e.BlobsBundle = dec.BlobsBundle
|
||||||
}
|
}
|
||||||
if dec.Requests != nil {
|
|
||||||
e.Requests = make([][]byte, len(dec.Requests))
|
|
||||||
for k, v := range dec.Requests {
|
|
||||||
e.Requests[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dec.Override != nil {
|
if dec.Override != nil {
|
||||||
e.Override = *dec.Override
|
e.Override = *dec.Override
|
||||||
}
|
}
|
||||||
if dec.Witness != nil {
|
|
||||||
e.Witness = dec.Witness
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ type ExecutableData struct {
|
|||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
||||||
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
||||||
|
Deposits types.Deposits `json:"depositRequests"`
|
||||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,23 +94,13 @@ type executableDataMarshaling struct {
|
|||||||
ExcessBlobGas *hexutil.Uint64
|
ExcessBlobGas *hexutil.Uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatelessPayloadStatusV1 is the result of a stateless payload execution.
|
|
||||||
type StatelessPayloadStatusV1 struct {
|
|
||||||
Status string `json:"status"`
|
|
||||||
StateRoot common.Hash `json:"stateRoot"`
|
|
||||||
ReceiptsRoot common.Hash `json:"receiptsRoot"`
|
|
||||||
ValidationError *string `json:"validationError"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go
|
//go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go
|
||||||
|
|
||||||
type ExecutionPayloadEnvelope struct {
|
type ExecutionPayloadEnvelope struct {
|
||||||
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
|
||||||
BlockValue *big.Int `json:"blockValue" gencodec:"required"`
|
BlockValue *big.Int `json:"blockValue" gencodec:"required"`
|
||||||
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
|
||||||
Requests [][]byte `json:"executionRequests"`
|
|
||||||
Override bool `json:"shouldOverrideBuilder"`
|
Override bool `json:"shouldOverrideBuilder"`
|
||||||
Witness *hexutil.Bytes `json:"witness,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlobsBundleV1 struct {
|
type BlobsBundleV1 struct {
|
||||||
@@ -118,22 +109,15 @@ type BlobsBundleV1 struct {
|
|||||||
Blobs []hexutil.Bytes `json:"blobs"`
|
Blobs []hexutil.Bytes `json:"blobs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlobAndProofV1 struct {
|
|
||||||
Blob hexutil.Bytes `json:"blob"`
|
|
||||||
Proof hexutil.Bytes `json:"proof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSON type overrides for ExecutionPayloadEnvelope.
|
// JSON type overrides for ExecutionPayloadEnvelope.
|
||||||
type executionPayloadEnvelopeMarshaling struct {
|
type executionPayloadEnvelopeMarshaling struct {
|
||||||
BlockValue *hexutil.Big
|
BlockValue *hexutil.Big
|
||||||
Requests []hexutil.Bytes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PayloadStatusV1 struct {
|
type PayloadStatusV1 struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Witness *hexutil.Bytes `json:"witness"`
|
LatestValidHash *common.Hash `json:"latestValidHash"`
|
||||||
LatestValidHash *common.Hash `json:"latestValidHash"`
|
ValidationError *string `json:"validationError"`
|
||||||
ValidationError *string `json:"validationError"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TransitionConfigurationV1 struct {
|
type TransitionConfigurationV1 struct {
|
||||||
@@ -213,21 +197,7 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
|
|||||||
// and that the blockhash of the constructed block matches the parameters. Nil
|
// and that the blockhash of the constructed block matches the parameters. Nil
|
||||||
// Withdrawals value will propagate through the returned block. Empty
|
// Withdrawals value will propagate through the returned block. Empty
|
||||||
// Withdrawals value must be passed via non-nil, length 0 value in data.
|
// Withdrawals value must be passed via non-nil, length 0 value in data.
|
||||||
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) {
|
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
|
||||||
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot, requests)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if block.Hash() != data.BlockHash {
|
|
||||||
return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", data.BlockHash, block.Hash())
|
|
||||||
}
|
|
||||||
return block, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExecutableDataToBlockNoHash is analogous to ExecutableDataToBlock, but is used
|
|
||||||
// for stateless execution, so it skips checking if the executable data hashes to
|
|
||||||
// the requested hash (stateless has to *compute* the root hash, it's not given).
|
|
||||||
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) {
|
|
||||||
txs, err := decodeTransactions(data.Transactions)
|
txs, err := decodeTransactions(data.Transactions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -262,21 +232,19 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
|||||||
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
|
h := types.DeriveSha(types.Withdrawals(data.Withdrawals), trie.NewStackTrie(nil))
|
||||||
withdrawalsRoot = &h
|
withdrawalsRoot = &h
|
||||||
}
|
}
|
||||||
|
// Compute requestsHash if any requests are non-nil.
|
||||||
var requestsHash *common.Hash
|
var (
|
||||||
if requests != nil {
|
requestsHash *common.Hash
|
||||||
// Put back request type byte.
|
requests types.Requests
|
||||||
typedRequests := make([][]byte, len(requests))
|
)
|
||||||
for i, reqdata := range requests {
|
if data.Deposits != nil {
|
||||||
typedReqdata := make([]byte, len(reqdata)+1)
|
requests = make(types.Requests, 0)
|
||||||
typedReqdata[0] = byte(i)
|
for _, d := range data.Deposits {
|
||||||
copy(typedReqdata[1:], reqdata)
|
requests = append(requests, types.NewRequest(d))
|
||||||
typedRequests[i] = typedReqdata
|
|
||||||
}
|
}
|
||||||
h := types.CalcRequestsHash(typedRequests)
|
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
|
||||||
requestsHash = &h
|
requestsHash = &h
|
||||||
}
|
}
|
||||||
|
|
||||||
header := &types.Header{
|
header := &types.Header{
|
||||||
ParentHash: data.ParentHash,
|
ParentHash: data.ParentHash,
|
||||||
UncleHash: types.EmptyUncleHash,
|
UncleHash: types.EmptyUncleHash,
|
||||||
@@ -299,15 +267,18 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
|||||||
ParentBeaconRoot: beaconRoot,
|
ParentBeaconRoot: beaconRoot,
|
||||||
RequestsHash: requestsHash,
|
RequestsHash: requestsHash,
|
||||||
}
|
}
|
||||||
return types.NewBlockWithHeader(header).
|
block := types.NewBlockWithHeader(header)
|
||||||
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}).
|
block = block.WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals, Requests: requests})
|
||||||
WithWitness(data.ExecutionWitness),
|
block = block.WithWitness(data.ExecutionWitness)
|
||||||
nil
|
if block.Hash() != data.BlockHash {
|
||||||
|
return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", data.BlockHash, block.Hash())
|
||||||
|
}
|
||||||
|
return block, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockToExecutableData constructs the ExecutableData structure by filling the
|
// BlockToExecutableData constructs the ExecutableData structure by filling the
|
||||||
// fields from the given block. It assumes the given block is post-merge block.
|
// fields from the given block. It assumes the given block is post-merge block.
|
||||||
func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar, requests [][]byte) *ExecutionPayloadEnvelope {
|
func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar) *ExecutionPayloadEnvelope {
|
||||||
data := &ExecutableData{
|
data := &ExecutableData{
|
||||||
BlockHash: block.Hash(),
|
BlockHash: block.Hash(),
|
||||||
ParentHash: block.ParentHash(),
|
ParentHash: block.ParentHash(),
|
||||||
@@ -328,8 +299,6 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
|||||||
ExcessBlobGas: block.ExcessBlobGas(),
|
ExcessBlobGas: block.ExcessBlobGas(),
|
||||||
ExecutionWitness: block.ExecutionWitness(),
|
ExecutionWitness: block.ExecutionWitness(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add blobs.
|
|
||||||
bundle := BlobsBundleV1{
|
bundle := BlobsBundleV1{
|
||||||
Commitments: make([]hexutil.Bytes, 0),
|
Commitments: make([]hexutil.Bytes, 0),
|
||||||
Blobs: make([]hexutil.Bytes, 0),
|
Blobs: make([]hexutil.Bytes, 0),
|
||||||
@@ -342,22 +311,22 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
|||||||
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
|
bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setRequests(block.Requests(), data)
|
||||||
|
return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove type byte in requests.
|
// setRequests differentiates the different request types and
|
||||||
var plainRequests [][]byte
|
// assigns them to the associated fields in ExecutableData.
|
||||||
|
func setRequests(requests types.Requests, data *ExecutableData) {
|
||||||
if requests != nil {
|
if requests != nil {
|
||||||
plainRequests = make([][]byte, len(requests))
|
// If requests is non-nil, it means deposits are available in block and we
|
||||||
for i, reqdata := range requests {
|
// should return an empty slice instead of nil if there are no deposits.
|
||||||
plainRequests[i] = reqdata[1:]
|
data.Deposits = make(types.Deposits, 0)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
for _, r := range requests {
|
||||||
return &ExecutionPayloadEnvelope{
|
if d, ok := r.Inner().(*types.Deposit); ok {
|
||||||
ExecutionPayload: data,
|
data.Deposits = append(data.Deposits, d)
|
||||||
BlockValue: fees,
|
}
|
||||||
BlobsBundle: &bundle,
|
|
||||||
Requests: plainRequests,
|
|
||||||
Override: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,6 +334,7 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
|||||||
type ExecutionPayloadBody struct {
|
type ExecutionPayloadBody struct {
|
||||||
TransactionData []hexutil.Bytes `json:"transactions"`
|
TransactionData []hexutil.Bytes `json:"transactions"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
|
Deposits types.Deposits `json:"depositRequests"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client identifiers to support ClientVersionV1.
|
// Client identifiers to support ClientVersionV1.
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ type CommitteeChain struct {
|
|||||||
sigVerifier committeeSigVerifier // BLS sig verifier (dummy verifier in tests)
|
sigVerifier committeeSigVerifier // BLS sig verifier (dummy verifier in tests)
|
||||||
|
|
||||||
config *types.ChainConfig
|
config *types.ChainConfig
|
||||||
|
signerThreshold int
|
||||||
minimumUpdateScore types.UpdateScore
|
minimumUpdateScore types.UpdateScore
|
||||||
enforceTime bool // enforceTime specifies whether the age of a signed header should be checked
|
enforceTime bool // enforceTime specifies whether the age of a signed header should be checked
|
||||||
}
|
}
|
||||||
@@ -95,13 +96,14 @@ func NewTestCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, si
|
|||||||
// clock source and signature verification for testing purposes.
|
// clock source and signature verification for testing purposes.
|
||||||
func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain {
|
func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain {
|
||||||
s := &CommitteeChain{
|
s := &CommitteeChain{
|
||||||
committeeCache: lru.NewCache[uint64, syncCommittee](10),
|
committeeCache: lru.NewCache[uint64, syncCommittee](10),
|
||||||
db: db,
|
db: db,
|
||||||
sigVerifier: sigVerifier,
|
sigVerifier: sigVerifier,
|
||||||
clock: clock,
|
clock: clock,
|
||||||
unixNano: unixNano,
|
unixNano: unixNano,
|
||||||
config: config,
|
config: config,
|
||||||
enforceTime: enforceTime,
|
signerThreshold: signerThreshold,
|
||||||
|
enforceTime: enforceTime,
|
||||||
minimumUpdateScore: types.UpdateScore{
|
minimumUpdateScore: types.UpdateScore{
|
||||||
SignerCount: uint32(signerThreshold),
|
SignerCount: uint32(signerThreshold),
|
||||||
SubPeriodIndex: params.SyncPeriodLength / 16,
|
SubPeriodIndex: params.SyncPeriodLength / 16,
|
||||||
|
|||||||
@@ -69,13 +69,12 @@ func (h *HeadTracker) ValidatedFinality() (types.FinalityUpdate, bool) {
|
|||||||
// slot or same slot and more signers) then ValidatedOptimistic is updated.
|
// slot or same slot and more signers) then ValidatedOptimistic is updated.
|
||||||
// The boolean return flag signals if ValidatedOptimistic has been changed.
|
// The boolean return flag signals if ValidatedOptimistic has been changed.
|
||||||
func (h *HeadTracker) ValidateOptimistic(update types.OptimisticUpdate) (bool, error) {
|
func (h *HeadTracker) ValidateOptimistic(update types.OptimisticUpdate) (bool, error) {
|
||||||
if err := update.Validate(); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
h.lock.Lock()
|
h.lock.Lock()
|
||||||
defer h.lock.Unlock()
|
defer h.lock.Unlock()
|
||||||
|
|
||||||
|
if err := update.Validate(); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
replace, err := h.validate(update.SignedHeader(), h.optimisticUpdate.SignedHeader())
|
replace, err := h.validate(update.SignedHeader(), h.optimisticUpdate.SignedHeader())
|
||||||
if replace {
|
if replace {
|
||||||
h.optimisticUpdate, h.hasOptimisticUpdate = update, true
|
h.optimisticUpdate, h.hasOptimisticUpdate = update, true
|
||||||
@@ -89,13 +88,12 @@ func (h *HeadTracker) ValidateOptimistic(update types.OptimisticUpdate) (bool, e
|
|||||||
// slot or same slot and more signers) then ValidatedFinality is updated.
|
// slot or same slot and more signers) then ValidatedFinality is updated.
|
||||||
// The boolean return flag signals if ValidatedFinality has been changed.
|
// The boolean return flag signals if ValidatedFinality has been changed.
|
||||||
func (h *HeadTracker) ValidateFinality(update types.FinalityUpdate) (bool, error) {
|
func (h *HeadTracker) ValidateFinality(update types.FinalityUpdate) (bool, error) {
|
||||||
if err := update.Validate(); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
h.lock.Lock()
|
h.lock.Lock()
|
||||||
defer h.lock.Unlock()
|
defer h.lock.Unlock()
|
||||||
|
|
||||||
|
if err := update.Validate(); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
replace, err := h.validate(update.SignedHeader(), h.finalityUpdate.SignedHeader())
|
replace, err := h.validate(update.SignedHeader(), h.finalityUpdate.SignedHeader())
|
||||||
if replace {
|
if replace {
|
||||||
h.finalityUpdate, h.hasFinalityUpdate = update, true
|
h.finalityUpdate, h.hasFinalityUpdate = update, true
|
||||||
|
|||||||
@@ -5,88 +5,88 @@
|
|||||||
# https://github.com/ethereum/execution-spec-tests/releases/download/v2.1.0/
|
# https://github.com/ethereum/execution-spec-tests/releases/download/v2.1.0/
|
||||||
ca89c76851b0900bfcc3cbb9a26cbece1f3d7c64a3bed38723e914713290df6c fixtures_develop.tar.gz
|
ca89c76851b0900bfcc3cbb9a26cbece1f3d7c64a3bed38723e914713290df6c fixtures_develop.tar.gz
|
||||||
|
|
||||||
# version:golang 1.23.2
|
# version:golang 1.23.1
|
||||||
# https://go.dev/dl/
|
# https://go.dev/dl/
|
||||||
36930162a93df417d90bd22c6e14daff4705baac2b02418edda671cdfa9cd07f go1.23.2.src.tar.gz
|
6ee44e298379d146a5e5aa6b1c5b5d5f5d0a3365eabdd70741e6e21340ec3b0d go1.23.1.src.tar.gz
|
||||||
025d77f1780906142023a364c31a572afd7d56d3a3be1e4e562e367ca88d3267 go1.23.2.freebsd-amd64.tar.gz
|
f17f2791717c15728ec63213a014e244c35f9c8846fb29f5a1b63d0c0556f756 go1.23.1.aix-ppc64.tar.gz
|
||||||
0d50bade977b84e173cb350946087f5de8c75f8df19456c3b60c5d58e186089d go1.23.2.windows-arm64.zip
|
dd9e772686ed908bcff94b6144322d4e2473a7dcd7c696b7e8b6d12f23c887fd go1.23.1.darwin-amd64.pkg
|
||||||
0edd985dbd6de64d9c88dbc8835bae21203c58444bf26fce0739cbec4eb1b610 go1.23.2.windows-arm64.msi
|
488d9e4ca3e3ed513ee4edd91bef3a2360c65fa6d6be59cf79640bf840130a58 go1.23.1.darwin-amd64.tar.gz
|
||||||
2283d12dfe7c8c8a46a41bbf7d11fe007434e7590cd1b89e221e478640b7ee3a go1.23.2.linux-mips64le.tar.gz
|
be34b488157ec69d94e26e1554558219a2c90789bcb7e3686965a7f9c8cfcbe7 go1.23.1.darwin-arm64.pkg
|
||||||
2293c5c3ffc595418308b4059ce214b99f0383cba83232e47a1a8c3b710c24e8 go1.23.2.linux-loong64.tar.gz
|
e223795ca340e285a760a6446ce57a74500b30e57469a4109961d36184d3c05a go1.23.1.darwin-arm64.tar.gz
|
||||||
23b93144e754bbcf5eda700e9decbdbd44d29ceedb1bf1de75f95e8a6ea986bb go1.23.2.openbsd-arm64.tar.gz
|
6af626176923a6ae6c5de6dc1c864f38365793c0e4ecd0d6eab847bdc23953e5 go1.23.1.dragonfly-amd64.tar.gz
|
||||||
2734a5b54905cea45f136c28249e626d0241b865b0637fa1db64bf533d9d843e go1.23.2.netbsd-amd64.tar.gz
|
cc957c1a019702e6cdc2e257202d42799011ebc1968b6c3bcd6b1965952607d5 go1.23.1.freebsd-386.tar.gz
|
||||||
28af3c40687afdda6b33b300833b6d662716cc2d624fb9fd61a49bdad44cd869 go1.23.2.freebsd-arm.tar.gz
|
a7d57781c50bb80886a8f04066791956d45aa3eea0f83070c5268b6223afb2ff go1.23.1.freebsd-amd64.tar.gz
|
||||||
367d522b47c7ce7761a671efcb8b12c8af8f509db1cd6160c91f410ef3201987 go1.23.2.windows-arm.msi
|
c7b09f3fef456048e596db9bea746eb66796aeb82885622b0388feee18f36a3e go1.23.1.freebsd-arm.tar.gz
|
||||||
36b7228bae235eee6c8193f5a956e1a9a17874955affb86b3564709b0fab5874 go1.23.2.linux-mipsle.tar.gz
|
b05cd6a77995a0c8439d88df124811c725fb78b942d0b6dd1643529d7ba62f1f go1.23.1.freebsd-arm64.tar.gz
|
||||||
3bd1130a08195d23960b154d2e6eaa80ac7325ebd9d01d74c58b6d12580e6b12 go1.23.2.linux-mips.tar.gz
|
56236ae70be1613f2915943b94f53c96be5bffc0719314078facd778a89bc57e go1.23.1.freebsd-riscv64.tar.gz
|
||||||
3bf66879b38a233c5cbb5d2eb982004117f05d6bf06279e886e087d7c504427d go1.23.2.openbsd-riscv64.tar.gz
|
8644c52df4e831202114fd67c9fcaf1f7233ad27bf945ac53fa7217cf1a0349f go1.23.1.illumos-amd64.tar.gz
|
||||||
3e80b943d70c7e1633822b42c1aa7234e61da14f13ff8efff7ee6e1347f37648 go1.23.2.netbsd-arm64.tar.gz
|
cdee2f4e2efa001f7ee75c90f2efc310b63346cfbba7b549987e9139527c6b17 go1.23.1.linux-386.tar.gz
|
||||||
40c0b61971a1a74fd4566c536f682c9d4976fa71d40d9daabc875c06113d0fee go1.23.2.darwin-amd64.pkg
|
49bbb517cfa9eee677e1e7897f7cf9cfdbcf49e05f61984a2789136de359f9bd go1.23.1.linux-amd64.tar.gz
|
||||||
445c0ef19d8692283f4c3a92052cc0568f5a048f4e546105f58e991d4aea54f5 go1.23.2.darwin-amd64.tar.gz
|
faec7f7f8ae53fda0f3d408f52182d942cc89ef5b7d3d9f23ff117437d4b2d2f go1.23.1.linux-arm64.tar.gz
|
||||||
542d3c1705f1c6a1c5a80d5dc62e2e45171af291e755d591c5e6531ef63b454e go1.23.2.linux-amd64.tar.gz
|
6c7832c7dcd8fb6d4eb308f672a725393403c74ee7be1aeccd8a443015df99de go1.23.1.linux-armv6l.tar.gz
|
||||||
560aff7fe1eeadc32248db35ed5c0a81e190d171b6ecec404cf46d808c13e92f go1.23.2.aix-ppc64.tar.gz
|
649ce3856ddc808c00b14a46232eab0bf95e7911cdf497010b17d76656f5ca4e go1.23.1.linux-loong64.tar.gz
|
||||||
5611cd648f5100b73a7d6fd85589a481af18fdbaf9c153a92de9a8e39a6e061f go1.23.2.darwin-arm64.pkg
|
201911048f234e5a0c51ec94b1a11d4e47062fee4398b1d2faa6c820dc026724 go1.23.1.linux-mips.tar.gz
|
||||||
695aac64532da8d9a243601ffa0411cd763be891fcf7fd2e857eea4ab10b8bcc go1.23.2.plan9-386.tar.gz
|
2bce3743df463915e45d2612f9476ffb03d0b3750b1cb3879347de08715b5fc6 go1.23.1.linux-mips64.tar.gz
|
||||||
69b31edcd3d4f7d8bbf9aee2b25cafba30b444ef19bc7a033e15026f7d0cc5c2 go1.23.2.netbsd-arm.tar.gz
|
54e301f266e33431b0703136e0bbd4cf02461b1ecedd37b7cbd90cb862a98e5f go1.23.1.linux-mips64le.tar.gz
|
||||||
6ffa4ac1f4368a3121a032917577a4e0a3feaf696c3e98f213b74ac04c318bc4 go1.23.2.plan9-arm.tar.gz
|
8efd495e93d17408c0803595cdc3bf13cb28e0f957aeabd9cc18245fb8e64019 go1.23.1.linux-mipsle.tar.gz
|
||||||
72a6def70300cc804c70073d8b579603d9b39b39b02b3b5d340968d9e7e0e9d4 go1.23.2.windows-386.msi
|
52bd68689095831ad9af7160844c23b28bb8d0acd268de7e300ff5f0662b7a07 go1.23.1.linux-ppc64.tar.gz
|
||||||
791ca685ee5ca0f6fe849dc078145cb1323d0ea9dd308e9cca9ba2e7186dbb3d go1.23.2.linux-ppc64.tar.gz
|
042888cae54b5fbfd9dd1e3b6bc4a5134879777fe6497fc4c62ec394b5ecf2da go1.23.1.linux-ppc64le.tar.gz
|
||||||
86b5de91fdf7bd9b52c77c62f8762518cf3fc256fe912af9bbff1d073054aa5b go1.23.2.plan9-amd64.tar.gz
|
1a4a609f0391bea202d9095453cbfaf7368fa88a04c206bf9dd715a738664dc3 go1.23.1.linux-riscv64.tar.gz
|
||||||
8734c7cd464a0620f6605bd3f9256bed062f262d0d58e4f45099c329a08ed966 go1.23.2.openbsd-amd64.tar.gz
|
47dc49ad45c45e192efa0df7dc7bc5403f5f2d15b5d0dc74ef3018154b616f4d go1.23.1.linux-s390x.tar.gz
|
||||||
980ceb889915695d94b166ca1300250dba76fa37a2d41eca2c5e7727dcb4fb7f go1.23.2.openbsd-arm.tar.gz
|
fbfbd5efa6a5d581ea7f5e65015f927db0e52135cab057e43d39d5482da54b61 go1.23.1.netbsd-386.tar.gz
|
||||||
a0cf25f236a0fa0a465816fe7f5c930f3b0b90c5c247b09c43a6adeff654e6ae go1.23.2.linux-mips64.tar.gz
|
e96e1cc5cf36113ee6099d1a7306b22cd9c3f975a36bdff954c59f104f22b853 go1.23.1.netbsd-amd64.tar.gz
|
||||||
a13cc0d621af4f35afd90b886c60b1bf66f771939d226dc36fa61a337d90eb30 go1.23.2.openbsd-ppc64.tar.gz
|
c394dfc06bfc276a591209a37e09cd39089ec9a9cc3db30b94814ce2e39eb1d4 go1.23.1.netbsd-arm.tar.gz
|
||||||
b29ff163b34cb4943c521fcfc1d956eaa6286561089042051a3fab22e79e9283 go1.23.2.windows-arm.zip
|
b3b35d64f32821a68b3e2994032dbefb81978f2ec3f218c7a770623b82d36b8e go1.23.1.netbsd-arm64.tar.gz
|
||||||
bc28fe3002cd65cec65d0e4f6000584dacb8c71bfaff8801dfb532855ca42513 go1.23.2.windows-amd64.zip
|
3c775c4c16c182e33c2c4ac090d9a247a93b3fb18a3df01d87d490f29599faff go1.23.1.openbsd-386.tar.gz
|
||||||
c164ce7d894b10fd861d7d7b96f1dbea3f993663d9f0c30bc4f8ae3915db8b0c go1.23.2.linux-ppc64le.tar.gz
|
5edbe53b47c57b32707fd7154536fbe9eaa79053fea01650c93b54cdba13fc0f go1.23.1.openbsd-amd64.tar.gz
|
||||||
c4ae1087dce4daf45a837f5fca36ac0e29a02ada9addf857f1c426e60bce6f21 go1.23.2.netbsd-386.tar.gz
|
c30903dd8fa98b8aca8e9db0962ce9f55502aed93e0ef41e5ae148aaa0088de1 go1.23.1.openbsd-arm.tar.gz
|
||||||
c80cbc5e66d6fb8b0c3300b0dda1fe925c429e199954d3327da2933d9870b041 go1.23.2.windows-amd64.msi
|
12da183489e58f9c6b357bc1b626f85ed7d4220cab31a49d6a49e6ac6a718b67 go1.23.1.openbsd-arm64.tar.gz
|
||||||
cb1ed4410f68d8be1156cee0a74fcfbdcd9bca377c83db3a9e1b07eebc6d71ef go1.23.2.linux-386.tar.gz
|
9cc9aad37696a4a10c31dcec9e35a308de0b369dad354d54cf07406ac6fa7c6f go1.23.1.openbsd-ppc64.tar.gz
|
||||||
d1fde255843fec1f7f0611d468effd98e1f4309f589ac13037db07b032f9da35 go1.23.2.openbsd-386.tar.gz
|
e1d740dda062ce5a276a0c3ed7d8b6353238bc8ff405f63e2e3480bfd26a5ec5 go1.23.1.openbsd-riscv64.tar.gz
|
||||||
d47e40366cd6c6b6ee14b811554cd7dde0351309f4a8a4569ec5ba2bd7689437 go1.23.2.illumos-amd64.tar.gz
|
da2a37f9987f01f096859230aa13ecc4ad2e7884465bce91004bc78c64435d65 go1.23.1.plan9-386.tar.gz
|
||||||
d87031194fe3e01abdcaf3c7302148ade97a7add6eac3fec26765bcb3207b80f go1.23.2.darwin-arm64.tar.gz
|
fd8fff8b0697d55c4a4d02a8dc998192b80a9dc2a057647373d6ff607cad29de go1.23.1.plan9-amd64.tar.gz
|
||||||
de1f94d7dd3548ba3036de1ea97eb8243881c22a88fcc04cc08c704ded769e02 go1.23.2.linux-s390x.tar.gz
|
52efbc5804c1c86ba7868aa8ebbc31cc8c2a27b62a60fd57944970d48fc67525 go1.23.1.plan9-arm.tar.gz
|
||||||
e3286bdde186077e65e961cbe18874d42a461e5b9c472c26572b8d4a98d15c40 go1.23.2.linux-armv6l.tar.gz
|
f54205f21e2143f2ada1bf1c00ddf64590f5139d5c3fb77cc06175f0d8cc7567 go1.23.1.solaris-amd64.tar.gz
|
||||||
e4d9a1319dfdaa827407855e406c43e85c878a1f93f4f3984c85dce969c8bf70 go1.23.2.freebsd-386.tar.gz
|
369a17f0cfd29e5c848e58ffe0d772da20abe334d1c7ca01dbcd55bb3db0b440 go1.23.1.windows-386.msi
|
||||||
ea8ab49c5c04c9f94a3f4894d1b030fbce8d10413905fa399f6c39c0a44d5556 go1.23.2.linux-riscv64.tar.gz
|
ab866f47d7be56e6b1c67f1d529bf4c23331a339fb0785f435a0552d352cb257 go1.23.1.windows-386.zip
|
||||||
eaa3bc377badbdcae144633f8b29bf2680475b72dcd4c135343d3bdc0ba7671e go1.23.2.windows-386.zip
|
e99dac215ee437b9bb8f8b14bbfe0e8756882c1ed291f30818e8363bc9c047a5 go1.23.1.windows-amd64.msi
|
||||||
f11b9b4d4a0679909202fc5e88093d6ff720a8a417bfe6a34d502c3862367039 go1.23.2.freebsd-riscv64.tar.gz
|
32dedf277c86610e380e1765593edb66876f00223df71690bd6be68ee17675c0 go1.23.1.windows-amd64.zip
|
||||||
f163b99b03e4bbc64cd30363f1694a08fcd44094415db1f092f13f9d1bb7c28e go1.23.2.dragonfly-amd64.tar.gz
|
23169c79dc6b54e0dffb25be6b67425ad9759392a58309bc057430a9bf4c8f6a go1.23.1.windows-arm.msi
|
||||||
f45af3e1434175ff85620a74c07fb41d6844655f1f2cd2389c5fca6de000f58c go1.23.2.freebsd-arm64.tar.gz
|
1a57615a09f13534f88e9f2d7efd5743535d1a5719b19e520eef965a634f8efb go1.23.1.windows-arm.zip
|
||||||
f626cdd92fc21a88b31c1251f419c17782933a42903db87a174ce74eeecc66a9 go1.23.2.linux-arm64.tar.gz
|
313e1a543931ad8735b4df8969e00f5f4c2ef07be21f54015ede961a70263d35 go1.23.1.windows-arm64.msi
|
||||||
fa70d39ddeb6b55241a30b48d7af4e681c6a7d7104e8326c3bc1b12a75e091cc go1.23.2.solaris-amd64.tar.gz
|
64ad0954d2c33f556fb1018d62de091254aa6e3a94f1c8a8b16af0d3701d194e go1.23.1.windows-arm64.zip
|
||||||
|
|
||||||
# version:golangci 1.61.0
|
# version:golangci 1.59.0
|
||||||
# https://github.com/golangci/golangci-lint/releases/
|
# https://github.com/golangci/golangci-lint/releases/
|
||||||
# https://github.com/golangci/golangci-lint/releases/download/v1.61.0/
|
# https://github.com/golangci/golangci-lint/releases/download/v1.59.0/
|
||||||
5c280ef3284f80c54fd90d73dc39ca276953949da1db03eb9dd0fbf868cc6e55 golangci-lint-1.61.0-darwin-amd64.tar.gz
|
418acf7e255ddc0783e97129c9b03d9311b77826a5311d425a01c708a86417e7 golangci-lint-1.59.0-darwin-amd64.tar.gz
|
||||||
544334890701e4e04a6e574bc010bea8945205c08c44cced73745a6378012d36 golangci-lint-1.61.0-darwin-arm64.tar.gz
|
5f6a1d95a6dd69f6e328eb56dd311a38e04cfab79a1305fbf4957f4e203f47b6 golangci-lint-1.59.0-darwin-arm64.tar.gz
|
||||||
e885a6f561092055930ebd298914d80e8fd2e10d2b1e9942836c2c6a115301fa golangci-lint-1.61.0-freebsd-386.tar.gz
|
8899bf589185d49f747f3e5db9f0bde8a47245a100c64a3dd4d65e8e92cfc4f2 golangci-lint-1.59.0-freebsd-386.tar.gz
|
||||||
b13f6a3f11f65e7ff66b734d7554df3bbae0f485768848424e7554ed289e19c2 golangci-lint-1.61.0-freebsd-amd64.tar.gz
|
658212f138d9df2ac89427e22115af34bf387c0871d70f2a25101718946a014f golangci-lint-1.59.0-freebsd-amd64.tar.gz
|
||||||
cd8e7bbe5b8f33ed1597aa1cc588da96a3b9f22e1b9ae60d93511eae1a0ee8c5 golangci-lint-1.61.0-freebsd-armv6.tar.gz
|
4c6395ea40f314d3b6fa17d8997baab93464d5d1deeaab513155e625473bd03a golangci-lint-1.59.0-freebsd-armv6.tar.gz
|
||||||
7ade524dbd88bd250968f45e190af90e151fa5ee63dd6aa7f7bb90e8155db61d golangci-lint-1.61.0-freebsd-armv7.tar.gz
|
ff37da4fbaacdb6bbae70fdbdbb1ba932a859956f788c82822fa06bef5b7c6b3 golangci-lint-1.59.0-freebsd-armv7.tar.gz
|
||||||
0fe3cd8a1ed8d9f54f48670a5af3df056d6040d94017057f0f4d65c930660ad9 golangci-lint-1.61.0-illumos-amd64.tar.gz
|
439739469ed2bda182b1ec276d40c40e02f195537f78e3672996741ad223d6b6 golangci-lint-1.59.0-illumos-amd64.tar.gz
|
||||||
b463fc5053a612abd26393ebaff1d85d7d56058946f4f0f7bf25ed44ea899415 golangci-lint-1.61.0-linux-386.tar.gz
|
940801d46790e40d0a097d8fee34e2606f0ef148cd039654029b0b8750a15ed6 golangci-lint-1.59.0-linux-386.tar.gz
|
||||||
77cb0af99379d9a21d5dc8c38364d060e864a01bd2f3e30b5e8cc550c3a54111 golangci-lint-1.61.0-linux-amd64.tar.gz
|
3b14a439f33c4fff83dbe0349950d984042b9a1feb6c62f82787b598fc3ab5f4 golangci-lint-1.59.0-linux-amd64.tar.gz
|
||||||
af60ac05566d9351615cb31b4cc070185c25bf8cbd9b09c1873aa5ec6f3cc17e golangci-lint-1.61.0-linux-arm64.tar.gz
|
c57e6c0b0fa03089a2611dceddd5bc5d206716cccdff8b149da8baac598719a1 golangci-lint-1.59.0-linux-arm64.tar.gz
|
||||||
1f307f2fcc5d7d674062a967a0d83a7091e300529aa237ec6ad2b3dd14c897f5 golangci-lint-1.61.0-linux-armv6.tar.gz
|
93149e2d3b25ac754df9a23172403d8aa6d021a7e0d9c090a12f51897f68c9a0 golangci-lint-1.59.0-linux-armv6.tar.gz
|
||||||
3ad8cbaae75a547450844811300f99c4cd290277398e43d22b9eb1792d15af4c golangci-lint-1.61.0-linux-armv7.tar.gz
|
d10ac38239d9efee3ee87b55c96cdf3fa09e1a525babe3ffdaaf65ccc48cf3dc golangci-lint-1.59.0-linux-armv7.tar.gz
|
||||||
9be2ca67d961d7699079739cf6f7c8291c5183d57e34d1677de21ca19d0bd3ed golangci-lint-1.61.0-linux-loong64.tar.gz
|
047338114b4f0d5f08f0fb9a397b03cc171916ed0960be7dfb355c2320cd5e9c golangci-lint-1.59.0-linux-loong64.tar.gz
|
||||||
90d005e1648115ebf0861b408eab9c936079a24763e883058b0a227cd3135d31 golangci-lint-1.61.0-linux-mips64.tar.gz
|
5632df0f7f8fc03a80a266130faef0b5902d280cf60621f1b2bdc1aef6d97ee9 golangci-lint-1.59.0-linux-mips64.tar.gz
|
||||||
6d2ed4f49407115460b8c10ccfc40fd177e0887a48864a2879dd16e84ba2a48c golangci-lint-1.61.0-linux-mips64le.tar.gz
|
71dd638c82fa4439171e7126d2c7a32b5d103bfdef282cea40c83632cb3d1f4b golangci-lint-1.59.0-linux-mips64le.tar.gz
|
||||||
633089589af5a58b7430afb6eee107d4e9c99e8d91711ddc219eb13a07e8d3b8 golangci-lint-1.61.0-linux-ppc64le.tar.gz
|
6cf9ea0d34e91669948483f9ae7f07da319a879344373a1981099fbd890cde00 golangci-lint-1.59.0-linux-ppc64le.tar.gz
|
||||||
4c1a097d9e0d1b4a8144dae6a1f5583a38d662f3bdc1498c4e954b6ed856be98 golangci-lint-1.61.0-linux-riscv64.tar.gz
|
af0205fa6fbab197cee613c359947711231739095d21b5c837086233b36ad971 golangci-lint-1.59.0-linux-riscv64.tar.gz
|
||||||
30581d3c987d287b7064617f1a2694143e10dffc40bc25be6636006ee82d7e1c golangci-lint-1.61.0-linux-s390x.tar.gz
|
a9d2fb93f3c688ebccef94f5dc96c0b07c4d20bf6556cddebd8442159b0c80f6 golangci-lint-1.59.0-linux-s390x.tar.gz
|
||||||
42530bf8100bd43c07f5efe6d92148ba6c5a7a712d510c6f24be85af6571d5eb golangci-lint-1.61.0-netbsd-386.tar.gz
|
68ab4c57a847b8ace9679887f2f8b2b6760e57ee29dcde8c3f40dd8bb2654fa2 golangci-lint-1.59.0-netbsd-386.tar.gz
|
||||||
b8bb07c920f6601edf718d5e82ec0784fd590b0992b42b6ec18da99f26013ed4 golangci-lint-1.61.0-netbsd-amd64.tar.gz
|
d277b8b435c19406d00de4d509eadf5a024a5782878332e9a1b7c02bb76e87a7 golangci-lint-1.59.0-netbsd-amd64.tar.gz
|
||||||
353a51527c60bd0776b0891b03f247c791986f625fca689d121972c624e54198 golangci-lint-1.61.0-netbsd-arm64.tar.gz
|
83211656be8dcfa1545af4f92894409f412d1f37566798cb9460a526593ad62c golangci-lint-1.59.0-netbsd-arm64.tar.gz
|
||||||
957a6272c3137910514225704c5dac0723b9c65eb7d9587366a997736e2d7580 golangci-lint-1.61.0-netbsd-armv6.tar.gz
|
6c6866d28bf79fa9817a0f7d2b050890ed109cae80bdb4dfa39536a7226da237 golangci-lint-1.59.0-netbsd-armv6.tar.gz
|
||||||
a89eb28ff7f18f5cd52b914739360fa95cf2f643de4adeca46e26bec3a07e8d8 golangci-lint-1.61.0-netbsd-armv7.tar.gz
|
11587566363bd03ca586b7df9776ccaed569fcd1f3489930ac02f9375b307503 golangci-lint-1.59.0-netbsd-armv7.tar.gz
|
||||||
d8d74c43600b271393000717a4ed157d7a15bb85bab7db2efad9b63a694d4634 golangci-lint-1.61.0-windows-386.zip
|
466181a8967bafa495e41494f93a0bec829c2cf715de874583b0460b3b8ae2b8 golangci-lint-1.59.0-windows-386.zip
|
||||||
e7bc2a81929a50f830244d6d2e657cce4f19a59aff49fa9000176ff34fda64ce golangci-lint-1.61.0-windows-amd64.zip
|
3317d8a87a99a49a0a1321d295c010790e6dbf43ee96b318f4b8bb23eae7a565 golangci-lint-1.59.0-windows-amd64.zip
|
||||||
ed97c221596dd771e3dd9344872c140340bee2e819cd7a90afa1de752f1f2e0f golangci-lint-1.61.0-windows-arm64.zip
|
b3af955c7fceac8220a36fc799e1b3f19d3b247d32f422caac5f9845df8f7316 golangci-lint-1.59.0-windows-arm64.zip
|
||||||
4b365233948b13d02d45928a5c390045e00945e919747b9887b5f260247541ae golangci-lint-1.61.0-windows-armv6.zip
|
6f083c7d0c764e5a0e5bde46ee3e91ae357d80c194190fe1d9754392e9064c7e golangci-lint-1.59.0-windows-armv6.zip
|
||||||
595538fb64d152173959d28f6235227f9cd969a828e5af0c4e960d02af4ffd0e golangci-lint-1.61.0-windows-armv7.zip
|
3709b4dd425deadab27748778d08e03c0f804d7748f7dd5b6bb488d98aa031c7 golangci-lint-1.59.0-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!
|
||||||
#
|
#
|
||||||
|
|||||||
393
build/ci.go
393
build/ci.go
@@ -24,14 +24,9 @@ Usage: go run build/ci.go <command> <command flags/arguments>
|
|||||||
|
|
||||||
Available commands are:
|
Available commands are:
|
||||||
|
|
||||||
lint -- runs certain pre-selected linters
|
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
|
||||||
check_tidy -- verifies that everything is 'go mod tidy'-ed
|
test [ -coverage ] [ packages... ] -- runs the tests
|
||||||
check_generate -- verifies that everything is 'go generate'-ed
|
lint -- runs certain pre-selected linters
|
||||||
check_baddeps -- verifies that certain dependencies are avoided
|
|
||||||
|
|
||||||
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
|
|
||||||
test [ -coverage ] [ packages... ] -- runs the tests
|
|
||||||
|
|
||||||
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts
|
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts
|
||||||
importkeys -- imports signing keys from env
|
importkeys -- imports signing keys from env
|
||||||
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
|
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
|
||||||
@@ -44,22 +39,26 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cespare/cp"
|
"github.com/cespare/cp"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto/signify"
|
"github.com/ethereum/go-ethereum/crypto/signify"
|
||||||
"github.com/ethereum/go-ethereum/internal/build"
|
"github.com/ethereum/go-ethereum/internal/build"
|
||||||
"github.com/ethereum/go-ethereum/internal/version"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -111,7 +110,7 @@ var (
|
|||||||
// A debian package is created for all executables listed here.
|
// A debian package is created for all executables listed here.
|
||||||
debEthereum = debPackage{
|
debEthereum = debPackage{
|
||||||
Name: "ethereum",
|
Name: "ethereum",
|
||||||
Version: version.Semantic,
|
Version: params.Version,
|
||||||
Executables: debExecutables,
|
Executables: debExecutables,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,12 +121,11 @@ var (
|
|||||||
|
|
||||||
// Distros for which packages are created
|
// Distros for which packages are created
|
||||||
debDistros = []string{
|
debDistros = []string{
|
||||||
"xenial", // 16.04, EOL: 04/2026
|
"xenial", // 16.04, EOL: 04/2026
|
||||||
"bionic", // 18.04, EOL: 04/2028
|
"bionic", // 18.04, EOL: 04/2028
|
||||||
"focal", // 20.04, EOL: 04/2030
|
"focal", // 20.04, EOL: 04/2030
|
||||||
"jammy", // 22.04, EOL: 04/2032
|
"jammy", // 22.04, EOL: 04/2032
|
||||||
"noble", // 24.04, EOL: 04/2034
|
"noble", // 24.04, EOL: 04/2034
|
||||||
"oracular", // 24.10, EOL: 07/2025
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is where the tests should be unpacked.
|
// This is where the tests should be unpacked.
|
||||||
@@ -146,7 +144,7 @@ func executablePath(name string) string {
|
|||||||
func main() {
|
func main() {
|
||||||
log.SetFlags(log.Lshortfile)
|
log.SetFlags(log.Lshortfile)
|
||||||
|
|
||||||
if !build.FileExist(filepath.Join("build", "ci.go")) {
|
if !common.FileExist(filepath.Join("build", "ci.go")) {
|
||||||
log.Fatal("this script must be run from the root of the repository")
|
log.Fatal("this script must be run from the root of the repository")
|
||||||
}
|
}
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
@@ -159,16 +157,10 @@ func main() {
|
|||||||
doTest(os.Args[2:])
|
doTest(os.Args[2:])
|
||||||
case "lint":
|
case "lint":
|
||||||
doLint(os.Args[2:])
|
doLint(os.Args[2:])
|
||||||
case "check_tidy":
|
|
||||||
doCheckTidy()
|
|
||||||
case "check_generate":
|
|
||||||
doCheckGenerate()
|
|
||||||
case "check_baddeps":
|
|
||||||
doCheckBadDeps()
|
|
||||||
case "archive":
|
case "archive":
|
||||||
doArchive(os.Args[2:])
|
doArchive(os.Args[2:])
|
||||||
case "dockerx":
|
case "docker":
|
||||||
doDockerBuildx(os.Args[2:])
|
doDocker(os.Args[2:])
|
||||||
case "debsrc":
|
case "debsrc":
|
||||||
doDebianSource(os.Args[2:])
|
doDebianSource(os.Args[2:])
|
||||||
case "nsis":
|
case "nsis":
|
||||||
@@ -177,6 +169,8 @@ func main() {
|
|||||||
doPurge(os.Args[2:])
|
doPurge(os.Args[2:])
|
||||||
case "sanitycheck":
|
case "sanitycheck":
|
||||||
doSanityCheck()
|
doSanityCheck()
|
||||||
|
case "generate":
|
||||||
|
doGenerate()
|
||||||
default:
|
default:
|
||||||
log.Fatal("unknown command ", os.Args[1])
|
log.Fatal("unknown command ", os.Args[1])
|
||||||
}
|
}
|
||||||
@@ -211,6 +205,12 @@ func doInstall(cmdline []string) {
|
|||||||
// Configure the build.
|
// Configure the build.
|
||||||
gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...)
|
gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...)
|
||||||
|
|
||||||
|
// arm64 CI builders are memory-constrained and can't handle concurrent builds,
|
||||||
|
// better disable it. This check isn't the best, it should probably
|
||||||
|
// check for something in env instead.
|
||||||
|
if env.CI && runtime.GOARCH == "arm64" {
|
||||||
|
gobuild.Args = append(gobuild.Args, "-p", "1")
|
||||||
|
}
|
||||||
// We use -trimpath to avoid leaking local paths into the built executables.
|
// We use -trimpath to avoid leaking local paths into the built executables.
|
||||||
gobuild.Args = append(gobuild.Args, "-trimpath")
|
gobuild.Args = append(gobuild.Args, "-trimpath")
|
||||||
|
|
||||||
@@ -355,93 +355,128 @@ func downloadSpecTestFixtures(csdb *build.ChecksumDB, cachedir string) string {
|
|||||||
return filepath.Join(cachedir, base)
|
return filepath.Join(cachedir, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
// doCheckTidy assets that the Go modules files are tidied already.
|
// hashAllSourceFiles iterates all files under the top-level project directory
|
||||||
func doCheckTidy() {
|
// computing the hash of each file (excluding files within the tests
|
||||||
targets := []string{"go.mod", "go.sum"}
|
// subrepo)
|
||||||
|
func hashAllSourceFiles() (map[string]common.Hash, error) {
|
||||||
hashes, err := build.HashFiles(targets)
|
res := make(map[string]common.Hash)
|
||||||
|
err := filepath.WalkDir(".", func(path string, d os.DirEntry, err error) error {
|
||||||
|
if strings.HasPrefix(path, filepath.FromSlash("tests/testdata")) {
|
||||||
|
return filepath.SkipDir
|
||||||
|
}
|
||||||
|
if !d.Type().IsRegular() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// open the file and hash it
|
||||||
|
f, err := os.OpenFile(path, os.O_RDONLY, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hasher := sha256.New()
|
||||||
|
if _, err := io.Copy(hasher, f); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
res[path] = common.Hash(hasher.Sum(nil))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to hash go.mod/go.sum: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
build.MustRun(new(build.GoToolchain).Go("mod", "tidy"))
|
return res, nil
|
||||||
|
|
||||||
tidied, err := build.HashFiles(targets)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to rehash go.mod/go.sum: %v", err)
|
|
||||||
}
|
|
||||||
if updates := build.DiffHashes(hashes, tidied); len(updates) > 0 {
|
|
||||||
log.Fatalf("files changed on running 'go mod tidy': %v", updates)
|
|
||||||
}
|
|
||||||
fmt.Println("No untidy module files detected.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// doCheckGenerate ensures that re-generating generated files does not cause
|
// hashSourceFiles iterates the provided set of filepaths (relative to the top-level geth project directory)
|
||||||
// any mutations in the source file tree.
|
// computing the hash of each file.
|
||||||
func doCheckGenerate() {
|
func hashSourceFiles(files []string) (map[string]common.Hash, error) {
|
||||||
var (
|
res := make(map[string]common.Hash)
|
||||||
cachedir = flag.String("cachedir", "./build/cache", "directory for caching binaries.")
|
for _, filePath := range files {
|
||||||
)
|
f, err := os.OpenFile(filePath, os.O_RDONLY, 0666)
|
||||||
// Compute the origin hashes of all the files
|
if err != nil {
|
||||||
var hashes map[string][32]byte
|
return nil, err
|
||||||
|
}
|
||||||
var err error
|
hasher := sha256.New()
|
||||||
hashes, err = build.HashFolder(".", []string{"tests/testdata", "build/cache"})
|
if _, err := io.Copy(hasher, f); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
log.Fatal("Error computing hashes", "err", err)
|
}
|
||||||
|
res[filePath] = common.Hash(hasher.Sum(nil))
|
||||||
}
|
}
|
||||||
// Run any go generate steps we might be missing
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// compareHashedFilesets compares two maps (key is relative file path to top-level geth directory, value is its hash)
|
||||||
|
// and returns the list of file paths whose hashes differed.
|
||||||
|
func compareHashedFilesets(preHashes map[string]common.Hash, postHashes map[string]common.Hash) []string {
|
||||||
|
updates := []string{}
|
||||||
|
for path, postHash := range postHashes {
|
||||||
|
preHash, ok := preHashes[path]
|
||||||
|
if !ok || preHash != postHash {
|
||||||
|
updates = append(updates, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updates
|
||||||
|
}
|
||||||
|
|
||||||
|
func doGoModTidy() {
|
||||||
|
targetFiles := []string{"go.mod", "go.sum"}
|
||||||
|
preHashes, err := hashSourceFiles(targetFiles)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("failed to hash go.mod/go.sum", "err", err)
|
||||||
|
}
|
||||||
|
tc := new(build.GoToolchain)
|
||||||
|
c := tc.Go("mod", "tidy")
|
||||||
|
build.MustRun(c)
|
||||||
|
postHashes, err := hashSourceFiles(targetFiles)
|
||||||
|
updates := compareHashedFilesets(preHashes, postHashes)
|
||||||
|
for _, updatedFile := range updates {
|
||||||
|
fmt.Fprintf(os.Stderr, "changed file %s\n", updatedFile)
|
||||||
|
}
|
||||||
|
if len(updates) != 0 {
|
||||||
|
log.Fatal("go.sum and/or go.mod were updated by running 'go mod tidy'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// doGenerate ensures that re-generating generated files does not cause
|
||||||
|
// any mutations in the source file tree: i.e. all generated files were
|
||||||
|
// updated and committed. Any stale generated files are updated.
|
||||||
|
func doGenerate() {
|
||||||
var (
|
var (
|
||||||
protocPath = downloadProtoc(*cachedir)
|
tc = new(build.GoToolchain)
|
||||||
protocGenGoPath = downloadProtocGenGo(*cachedir)
|
cachedir = flag.String("cachedir", "./build/cache", "directory for caching binaries.")
|
||||||
|
verify = flag.Bool("verify", false, "check whether any files are changed by go generate")
|
||||||
)
|
)
|
||||||
c := new(build.GoToolchain).Go("generate", "./...")
|
|
||||||
|
protocPath := downloadProtoc(*cachedir)
|
||||||
|
protocGenGoPath := downloadProtocGenGo(*cachedir)
|
||||||
|
|
||||||
|
var preHashes map[string]common.Hash
|
||||||
|
if *verify {
|
||||||
|
var err error
|
||||||
|
preHashes, err = hashAllSourceFiles()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("failed to compute map of source hashes", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c := tc.Go("generate", "./...")
|
||||||
pathList := []string{filepath.Join(protocPath, "bin"), protocGenGoPath, os.Getenv("PATH")}
|
pathList := []string{filepath.Join(protocPath, "bin"), protocGenGoPath, os.Getenv("PATH")}
|
||||||
c.Env = append(c.Env, "PATH="+strings.Join(pathList, string(os.PathListSeparator)))
|
c.Env = append(c.Env, "PATH="+strings.Join(pathList, string(os.PathListSeparator)))
|
||||||
build.MustRun(c)
|
build.MustRun(c)
|
||||||
|
|
||||||
// Check if generate file hashes have changed
|
if !*verify {
|
||||||
generated, err := build.HashFolder(".", []string{"tests/testdata", "build/cache"})
|
return
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error re-computing hashes: %v", err)
|
|
||||||
}
|
}
|
||||||
updates := build.DiffHashes(hashes, generated)
|
// Check if files were changed.
|
||||||
for _, file := range updates {
|
postHashes, err := hashAllSourceFiles()
|
||||||
log.Printf("File changed: %s", file)
|
if err != nil {
|
||||||
|
log.Fatal("error computing source tree file hashes", "err", err)
|
||||||
|
}
|
||||||
|
updates := compareHashedFilesets(preHashes, postHashes)
|
||||||
|
for _, updatedFile := range updates {
|
||||||
|
fmt.Fprintf(os.Stderr, "changed file %s\n", updatedFile)
|
||||||
}
|
}
|
||||||
if len(updates) != 0 {
|
if len(updates) != 0 {
|
||||||
log.Fatal("One or more generated files were updated by running 'go generate ./...'")
|
log.Fatal("One or more generated files were updated by running 'go generate ./...'")
|
||||||
}
|
}
|
||||||
fmt.Println("No stale files detected.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// doCheckBadDeps verifies whether certain unintended dependencies between some
|
|
||||||
// packages leak into the codebase due to a refactor. This is not an exhaustive
|
|
||||||
// list, rather something we build up over time at sensitive places.
|
|
||||||
func doCheckBadDeps() {
|
|
||||||
baddeps := [][2]string{
|
|
||||||
// Rawdb tends to be a dumping ground for db utils, sometimes leaking the db itself
|
|
||||||
{"github.com/ethereum/go-ethereum/core/rawdb", "github.com/ethereum/go-ethereum/ethdb/leveldb"},
|
|
||||||
{"github.com/ethereum/go-ethereum/core/rawdb", "github.com/ethereum/go-ethereum/ethdb/pebbledb"},
|
|
||||||
}
|
|
||||||
tc := new(build.GoToolchain)
|
|
||||||
|
|
||||||
var failed bool
|
|
||||||
for _, rule := range baddeps {
|
|
||||||
out, err := tc.Go("list", "-deps", rule[0]).CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to list '%s' dependencies: %v", rule[0], err)
|
|
||||||
}
|
|
||||||
for _, line := range strings.Split(string(out), "\n") {
|
|
||||||
if strings.TrimSpace(line) == rule[1] {
|
|
||||||
log.Printf("Found bad dependency '%s' -> '%s'", rule[0], rule[1])
|
|
||||||
failed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if failed {
|
|
||||||
log.Fatalf("Bad dependencies detected.")
|
|
||||||
}
|
|
||||||
fmt.Println("No bad dependencies detected.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// doLint runs golangci-lint on requested packages.
|
// doLint runs golangci-lint on requested packages.
|
||||||
@@ -458,6 +493,8 @@ func doLint(cmdline []string) {
|
|||||||
linter := downloadLinter(*cachedir)
|
linter := downloadLinter(*cachedir)
|
||||||
lflags := []string{"run", "--config", ".golangci.yml"}
|
lflags := []string{"run", "--config", ".golangci.yml"}
|
||||||
build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
|
build.MustRunCommandWithOutput(linter, append(lflags, packages...)...)
|
||||||
|
|
||||||
|
doGoModTidy()
|
||||||
fmt.Println("You have achieved perfection.")
|
fmt.Println("You have achieved perfection.")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,7 +638,7 @@ func doArchive(cmdline []string) {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
env = build.Env()
|
env = build.Env()
|
||||||
basegeth = archiveBasename(*arch, version.Archive(env.Commit))
|
basegeth = archiveBasename(*arch, params.ArchiveVersion(env.Commit))
|
||||||
geth = "geth-" + basegeth + ext
|
geth = "geth-" + basegeth + ext
|
||||||
alltools = "geth-alltools-" + basegeth + ext
|
alltools = "geth-alltools-" + basegeth + ext
|
||||||
)
|
)
|
||||||
@@ -686,9 +723,10 @@ func maybeSkipArchive(env build.Environment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Builds the docker images and optionally uploads them to Docker Hub.
|
// Builds the docker images and optionally uploads them to Docker Hub.
|
||||||
func doDockerBuildx(cmdline []string) {
|
func doDocker(cmdline []string) {
|
||||||
var (
|
var (
|
||||||
platform = flag.String("platform", "", `Push a multi-arch docker image for the specified architectures (usually "linux/amd64,linux/arm64")`)
|
image = flag.Bool("image", false, `Whether to build and push an arch specific docker image`)
|
||||||
|
manifest = flag.String("manifest", "", `Push a multi-arch docker image for the specified architectures (usually "amd64,arm64")`)
|
||||||
upload = flag.String("upload", "", `Where to upload the docker image (usually "ethereum/client-go")`)
|
upload = flag.String("upload", "", `Where to upload the docker image (usually "ethereum/client-go")`)
|
||||||
)
|
)
|
||||||
flag.CommandLine.Parse(cmdline)
|
flag.CommandLine.Parse(cmdline)
|
||||||
@@ -721,28 +759,131 @@ func doDockerBuildx(cmdline []string) {
|
|||||||
case env.Branch == "master":
|
case env.Branch == "master":
|
||||||
tags = []string{"latest"}
|
tags = []string{"latest"}
|
||||||
case strings.HasPrefix(env.Tag, "v1."):
|
case strings.HasPrefix(env.Tag, "v1."):
|
||||||
tags = []string{"stable", fmt.Sprintf("release-%v", version.Family), "v" + version.Semantic}
|
tags = []string{"stable", fmt.Sprintf("release-1.%d", params.VersionMinor), "v" + params.Version}
|
||||||
}
|
}
|
||||||
// Need to create a mult-arch builder
|
// If architecture specific image builds are requested, build and push them
|
||||||
build.MustRunCommand("docker", "buildx", "create", "--use", "--name", "multi-arch-builder", "--platform", *platform)
|
if *image {
|
||||||
|
build.MustRunCommand("docker", "build", "--build-arg", "COMMIT="+env.Commit, "--build-arg", "VERSION="+params.VersionWithMeta, "--build-arg", "BUILDNUM="+env.Buildnum, "--tag", fmt.Sprintf("%s:TAG", *upload), ".")
|
||||||
|
build.MustRunCommand("docker", "build", "--build-arg", "COMMIT="+env.Commit, "--build-arg", "VERSION="+params.VersionWithMeta, "--build-arg", "BUILDNUM="+env.Buildnum, "--tag", fmt.Sprintf("%s:alltools-TAG", *upload), "-f", "Dockerfile.alltools", ".")
|
||||||
|
|
||||||
for _, spec := range []struct {
|
// Tag and upload the images to Docker Hub
|
||||||
file string
|
for _, tag := range tags {
|
||||||
base string
|
gethImage := fmt.Sprintf("%s:%s-%s", *upload, tag, runtime.GOARCH)
|
||||||
}{
|
toolImage := fmt.Sprintf("%s:alltools-%s-%s", *upload, tag, runtime.GOARCH)
|
||||||
{file: "Dockerfile", base: fmt.Sprintf("%s:", *upload)},
|
|
||||||
{file: "Dockerfile.alltools", base: fmt.Sprintf("%s:alltools-", *upload)},
|
// If the image already exists (non version tag), check the build
|
||||||
} {
|
// number to prevent overwriting a newer commit if concurrent builds
|
||||||
for _, tag := range tags { // latest, stable etc
|
// are running. This is still a tiny bit racey if two published are
|
||||||
gethImage := fmt.Sprintf("%s%s", spec.base, tag)
|
// done at the same time, but that's extremely unlikely even on the
|
||||||
build.MustRunCommand("docker", "buildx", "build",
|
// master branch.
|
||||||
"--build-arg", "COMMIT="+env.Commit,
|
for _, img := range []string{gethImage, toolImage} {
|
||||||
"--build-arg", "VERSION="+version.WithMeta,
|
if exec.Command("docker", "pull", img).Run() != nil {
|
||||||
"--build-arg", "BUILDNUM="+env.Buildnum,
|
continue // Generally the only failure is a missing image, which is good
|
||||||
"--tag", gethImage,
|
}
|
||||||
"--platform", *platform,
|
buildnum, err := exec.Command("docker", "inspect", "--format", "{{index .Config.Labels \"buildnum\"}}", img).CombinedOutput()
|
||||||
"--push",
|
if err != nil {
|
||||||
"--file", spec.file, ".")
|
log.Fatalf("Failed to inspect container: %v\nOutput: %s", err, string(buildnum))
|
||||||
|
}
|
||||||
|
buildnum = bytes.TrimSpace(buildnum)
|
||||||
|
|
||||||
|
if len(buildnum) > 0 && len(env.Buildnum) > 0 {
|
||||||
|
oldnum, err := strconv.Atoi(string(buildnum))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to parse old image build number: %v", err)
|
||||||
|
}
|
||||||
|
newnum, err := strconv.Atoi(env.Buildnum)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to parse current build number: %v", err)
|
||||||
|
}
|
||||||
|
if oldnum > newnum {
|
||||||
|
log.Fatalf("Current build number %d not newer than existing %d", newnum, oldnum)
|
||||||
|
} else {
|
||||||
|
log.Printf("Updating %s from build %d to %d", img, oldnum, newnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
build.MustRunCommand("docker", "image", "tag", fmt.Sprintf("%s:TAG", *upload), gethImage)
|
||||||
|
build.MustRunCommand("docker", "image", "tag", fmt.Sprintf("%s:alltools-TAG", *upload), toolImage)
|
||||||
|
build.MustRunCommand("docker", "push", gethImage)
|
||||||
|
build.MustRunCommand("docker", "push", toolImage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If multi-arch image manifest push is requested, assemble it
|
||||||
|
if len(*manifest) != 0 {
|
||||||
|
// Since different architectures are pushed by different builders, wait
|
||||||
|
// until all required images are updated.
|
||||||
|
var mismatch bool
|
||||||
|
for i := 0; i < 2; i++ { // 2 attempts, second is race check
|
||||||
|
mismatch = false // hope there's no mismatch now
|
||||||
|
|
||||||
|
for _, tag := range tags {
|
||||||
|
for _, arch := range strings.Split(*manifest, ",") {
|
||||||
|
gethImage := fmt.Sprintf("%s:%s-%s", *upload, tag, arch)
|
||||||
|
toolImage := fmt.Sprintf("%s:alltools-%s-%s", *upload, tag, arch)
|
||||||
|
|
||||||
|
for _, img := range []string{gethImage, toolImage} {
|
||||||
|
if out, err := exec.Command("docker", "pull", img).CombinedOutput(); err != nil {
|
||||||
|
log.Printf("Required image %s unavailable: %v\nOutput: %s", img, err, out)
|
||||||
|
mismatch = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buildnum, err := exec.Command("docker", "inspect", "--format", "{{index .Config.Labels \"buildnum\"}}", img).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to inspect container: %v\nOutput: %s", err, string(buildnum))
|
||||||
|
}
|
||||||
|
buildnum = bytes.TrimSpace(buildnum)
|
||||||
|
|
||||||
|
if string(buildnum) != env.Buildnum {
|
||||||
|
log.Printf("Build number mismatch on %s: want %s, have %s", img, env.Buildnum, buildnum)
|
||||||
|
mismatch = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if mismatch {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if mismatch {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if mismatch {
|
||||||
|
// Build numbers mismatching, retry in a short time to
|
||||||
|
// avoid concurrent fails in both publisher images. If
|
||||||
|
// however the retry failed too, it means the concurrent
|
||||||
|
// builder is still crunching, let that do the publish.
|
||||||
|
if i == 0 {
|
||||||
|
time.Sleep(30 * time.Second)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if mismatch {
|
||||||
|
log.Println("Relinquishing publish to other builder")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Assemble and push the Geth manifest image
|
||||||
|
for _, tag := range tags {
|
||||||
|
gethImage := fmt.Sprintf("%s:%s", *upload, tag)
|
||||||
|
|
||||||
|
var gethSubImages []string
|
||||||
|
for _, arch := range strings.Split(*manifest, ",") {
|
||||||
|
gethSubImages = append(gethSubImages, gethImage+"-"+arch)
|
||||||
|
}
|
||||||
|
build.MustRunCommand("docker", append([]string{"manifest", "create", gethImage}, gethSubImages...)...)
|
||||||
|
build.MustRunCommand("docker", "manifest", "push", gethImage)
|
||||||
|
}
|
||||||
|
// Assemble and push the alltools manifest image
|
||||||
|
for _, tag := range tags {
|
||||||
|
toolImage := fmt.Sprintf("%s:alltools-%s", *upload, tag)
|
||||||
|
|
||||||
|
var toolSubImages []string
|
||||||
|
for _, arch := range strings.Split(*manifest, ",") {
|
||||||
|
toolSubImages = append(toolSubImages, toolImage+"-"+arch)
|
||||||
|
}
|
||||||
|
build.MustRunCommand("docker", append([]string{"manifest", "create", toolImage}, toolSubImages...)...)
|
||||||
|
build.MustRunCommand("docker", "manifest", "push", toolImage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -884,7 +1025,7 @@ func ppaUpload(workdir, ppa, sshUser string, files []string) {
|
|||||||
var idfile string
|
var idfile string
|
||||||
if sshkey := getenvBase64("PPA_SSH_KEY"); len(sshkey) > 0 {
|
if sshkey := getenvBase64("PPA_SSH_KEY"); len(sshkey) > 0 {
|
||||||
idfile = filepath.Join(workdir, "sshkey")
|
idfile = filepath.Join(workdir, "sshkey")
|
||||||
if !build.FileExist(idfile) {
|
if !common.FileExist(idfile) {
|
||||||
os.WriteFile(idfile, sshkey, 0600)
|
os.WriteFile(idfile, sshkey, 0600)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1109,19 +1250,19 @@ func doWindowsInstaller(cmdline []string) {
|
|||||||
// Build the installer. This assumes that all the needed files have been previously
|
// Build the installer. This assumes that all the needed files have been previously
|
||||||
// built (don't mix building and packaging to keep cross compilation complexity to a
|
// built (don't mix building and packaging to keep cross compilation complexity to a
|
||||||
// minimum).
|
// minimum).
|
||||||
ver := strings.Split(version.Semantic, ".")
|
version := strings.Split(params.Version, ".")
|
||||||
if env.Commit != "" {
|
if env.Commit != "" {
|
||||||
ver[2] += "-" + env.Commit[:8]
|
version[2] += "-" + env.Commit[:8]
|
||||||
}
|
}
|
||||||
installer, err := filepath.Abs("geth-" + archiveBasename(*arch, version.Archive(env.Commit)) + ".exe")
|
installer, err := filepath.Abs("geth-" + archiveBasename(*arch, params.ArchiveVersion(env.Commit)) + ".exe")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to convert installer file path: %v", err)
|
log.Fatalf("Failed to convert installer file path: %v", err)
|
||||||
}
|
}
|
||||||
build.MustRunCommand("makensis.exe",
|
build.MustRunCommand("makensis.exe",
|
||||||
"/DOUTPUTFILE="+installer,
|
"/DOUTPUTFILE="+installer,
|
||||||
"/DMAJORVERSION="+ver[0],
|
"/DMAJORVERSION="+version[0],
|
||||||
"/DMINORVERSION="+ver[1],
|
"/DMINORVERSION="+version[1],
|
||||||
"/DBUILDVERSION="+ver[2],
|
"/DBUILDVERSION="+version[2],
|
||||||
"/DARCH="+*arch,
|
"/DARCH="+*arch,
|
||||||
filepath.Join(*workdir, "geth.nsi"),
|
filepath.Join(*workdir, "geth.nsi"),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/beacon/blsync"
|
"github.com/ethereum/go-ethereum/beacon/blsync"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
@@ -34,7 +33,7 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := flags.NewApp("beacon light syncer tool")
|
app := flags.NewApp("beacon light syncer tool")
|
||||||
app.Flags = slices.Concat([]cli.Flag{
|
app.Flags = flags.Merge([]cli.Flag{
|
||||||
utils.BeaconApiFlag,
|
utils.BeaconApiFlag,
|
||||||
utils.BeaconApiHeaderFlag,
|
utils.BeaconApiHeaderFlag,
|
||||||
utils.BeaconThresholdFlag,
|
utils.BeaconThresholdFlag,
|
||||||
@@ -46,7 +45,6 @@ func main() {
|
|||||||
//TODO datadir for optional permanent database
|
//TODO datadir for optional permanent database
|
||||||
utils.MainnetFlag,
|
utils.MainnetFlag,
|
||||||
utils.SepoliaFlag,
|
utils.SepoliaFlag,
|
||||||
utils.HoleskyFlag,
|
|
||||||
utils.BlsyncApiFlag,
|
utils.BlsyncApiFlag,
|
||||||
utils.BlsyncJWTSecretFlag,
|
utils.BlsyncJWTSecretFlag,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"slices"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -29,6 +28,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test"
|
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v4test"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
@@ -83,7 +83,7 @@ var (
|
|||||||
Name: "listen",
|
Name: "listen",
|
||||||
Usage: "Runs a discovery node",
|
Usage: "Runs a discovery node",
|
||||||
Action: discv4Listen,
|
Action: discv4Listen,
|
||||||
Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{
|
Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{
|
||||||
httpAddrFlag,
|
httpAddrFlag,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ var (
|
|||||||
Name: "crawl",
|
Name: "crawl",
|
||||||
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
||||||
Action: discv4Crawl,
|
Action: discv4Crawl,
|
||||||
Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}),
|
Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{crawlTimeoutFlag, crawlParallelismFlag}),
|
||||||
}
|
}
|
||||||
discv4TestCommand = &cli.Command{
|
discv4TestCommand = &cli.Command{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ package main
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test"
|
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/v5test"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
@@ -56,7 +56,7 @@ var (
|
|||||||
Name: "crawl",
|
Name: "crawl",
|
||||||
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
Usage: "Updates a nodes.json file with random nodes found in the DHT",
|
||||||
Action: discv5Crawl,
|
Action: discv5Crawl,
|
||||||
Flags: slices.Concat(discoveryNodeFlags, []cli.Flag{
|
Flags: flags.Merge(discoveryNodeFlags, []cli.Flag{
|
||||||
crawlTimeoutFlag,
|
crawlTimeoutFlag,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ func (c *Chain) AccountsInHashOrder() []state.DumpAccount {
|
|||||||
list := make([]state.DumpAccount, len(c.state))
|
list := make([]state.DumpAccount, len(c.state))
|
||||||
i := 0
|
i := 0
|
||||||
for addr, acc := range c.state {
|
for addr, acc := range c.state {
|
||||||
|
addr := addr
|
||||||
list[i] = acc
|
list[i] = acc
|
||||||
list[i].Address = &addr
|
list[i].Address = &addr
|
||||||
if len(acc.AddressHash) != 32 {
|
if len(acc.AddressHash) != 32 {
|
||||||
|
|||||||
@@ -286,6 +286,7 @@ a key before startingHash (wrong order). The server should return the first avai
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
|
tc := tc
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
t.Log("\n")
|
t.Log("\n")
|
||||||
}
|
}
|
||||||
@@ -428,6 +429,7 @@ of the test account. The server should return slots [2,3] (i.e. the 'next availa
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
|
tc := tc
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
t.Log("\n")
|
t.Log("\n")
|
||||||
}
|
}
|
||||||
@@ -524,6 +526,7 @@ func (s *Suite) TestSnapGetByteCodes(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
|
tc := tc
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
t.Log("\n")
|
t.Log("\n")
|
||||||
}
|
}
|
||||||
@@ -720,6 +723,7 @@ The server should reject the request.`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
|
tc := tc
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
t.Log("\n")
|
t.Log("\n")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"shanghaiTime": 780,
|
"shanghaiTime": 780,
|
||||||
"cancunTime": 840,
|
"cancunTime": 840,
|
||||||
"terminalTotalDifficulty": 9454784,
|
"terminalTotalDifficulty": 9454784,
|
||||||
|
"terminalTotalDifficultyPassed": true,
|
||||||
"ethash": {}
|
"ethash": {}
|
||||||
},
|
},
|
||||||
"nonce": "0x0",
|
"nonce": "0x0",
|
||||||
|
|||||||
@@ -1,200 +0,0 @@
|
|||||||
// Copyright 2023 The go-ethereum Authors
|
|
||||||
// This file is part of go-ethereum.
|
|
||||||
//
|
|
||||||
// go-ethereum is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// go-ethereum is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
|
||||||
"github.com/urfave/cli/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
jt = vm.NewPragueEOFInstructionSetForTesting()
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
jt vm.JumpTable
|
|
||||||
initcode = "INITCODE"
|
|
||||||
)
|
|
||||||
|
|
||||||
func eofParseAction(ctx *cli.Context) error {
|
|
||||||
// If `--test` is set, parse and validate the reference test at the provided path.
|
|
||||||
if ctx.IsSet(refTestFlag.Name) {
|
|
||||||
var (
|
|
||||||
file = ctx.String(refTestFlag.Name)
|
|
||||||
executedTests int
|
|
||||||
passedTests int
|
|
||||||
)
|
|
||||||
err := filepath.Walk(file, func(path string, info fs.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
log.Debug("Executing test", "name", info.Name())
|
|
||||||
passed, tot, err := executeTest(path)
|
|
||||||
passedTests += passed
|
|
||||||
executedTests += tot
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Info("Executed tests", "passed", passedTests, "total executed", executedTests)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// If `--hex` is set, parse and validate the hex string argument.
|
|
||||||
if ctx.IsSet(hexFlag.Name) {
|
|
||||||
if _, err := parseAndValidate(ctx.String(hexFlag.Name), false); err != nil {
|
|
||||||
return fmt.Errorf("err: %w", err)
|
|
||||||
}
|
|
||||||
fmt.Println("OK")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// If neither are passed in, read input from stdin.
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
|
||||||
scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024)
|
|
||||||
for scanner.Scan() {
|
|
||||||
l := strings.TrimSpace(scanner.Text())
|
|
||||||
if strings.HasPrefix(l, "#") || l == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err := parseAndValidate(l, false); err != nil {
|
|
||||||
fmt.Printf("err: %v\n", err)
|
|
||||||
} else {
|
|
||||||
fmt.Println("OK")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type refTests struct {
|
|
||||||
Vectors map[string]eOFTest `json:"vectors"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type eOFTest struct {
|
|
||||||
Code string `json:"code"`
|
|
||||||
Results map[string]etResult `json:"results"`
|
|
||||||
ContainerKind string `json:"containerKind"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type etResult struct {
|
|
||||||
Result bool `json:"result"`
|
|
||||||
Exception string `json:"exception,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func executeTest(path string) (int, int, error) {
|
|
||||||
src, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, err
|
|
||||||
}
|
|
||||||
var testsByName map[string]refTests
|
|
||||||
if err := json.Unmarshal(src, &testsByName); err != nil {
|
|
||||||
return 0, 0, err
|
|
||||||
}
|
|
||||||
passed, total := 0, 0
|
|
||||||
for testsName, tests := range testsByName {
|
|
||||||
for name, tt := range tests.Vectors {
|
|
||||||
for fork, r := range tt.Results {
|
|
||||||
total++
|
|
||||||
_, err := parseAndValidate(tt.Code, tt.ContainerKind == initcode)
|
|
||||||
if r.Result && err != nil {
|
|
||||||
log.Error("Test failure, expected validation success", "name", testsName, "idx", name, "fork", fork, "err", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !r.Result && err == nil {
|
|
||||||
log.Error("Test failure, expected validation error", "name", testsName, "idx", name, "fork", fork, "have err", r.Exception, "err", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
passed++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return passed, total, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseAndValidate(s string, isInitCode bool) (*vm.Container, error) {
|
|
||||||
if len(s) >= 2 && strings.HasPrefix(s, "0x") {
|
|
||||||
s = s[2:]
|
|
||||||
}
|
|
||||||
b, err := hex.DecodeString(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to decode data: %w", err)
|
|
||||||
}
|
|
||||||
return parse(b, isInitCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parse(b []byte, isInitCode bool) (*vm.Container, error) {
|
|
||||||
var c vm.Container
|
|
||||||
if err := c.UnmarshalBinary(b, isInitCode); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := c.ValidateCode(&jt, isInitCode); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func eofDumpAction(ctx *cli.Context) error {
|
|
||||||
// If `--hex` is set, parse and validate the hex string argument.
|
|
||||||
if ctx.IsSet(hexFlag.Name) {
|
|
||||||
return eofDump(ctx.String(hexFlag.Name))
|
|
||||||
}
|
|
||||||
// Otherwise read from stdin
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
|
||||||
scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024)
|
|
||||||
for scanner.Scan() {
|
|
||||||
l := strings.TrimSpace(scanner.Text())
|
|
||||||
if strings.HasPrefix(l, "#") || l == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := eofDump(l); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println("")
|
|
||||||
}
|
|
||||||
return scanner.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
func eofDump(hexdata string) error {
|
|
||||||
if len(hexdata) >= 2 && strings.HasPrefix(hexdata, "0x") {
|
|
||||||
hexdata = hexdata[2:]
|
|
||||||
}
|
|
||||||
b, err := hex.DecodeString(hexdata)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to decode data: %w", err)
|
|
||||||
}
|
|
||||||
var c vm.Container
|
|
||||||
if err := c.UnmarshalBinary(b, false); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println(c.String())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
)
|
|
||||||
|
|
||||||
func FuzzEofParsing(f *testing.F) {
|
|
||||||
// Seed with corpus from execution-spec-tests
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
fname := fmt.Sprintf("testdata/eof/eof_corpus_%d.txt", i)
|
|
||||||
corpus, err := os.Open(fname)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
f.Logf("Reading seed data from %v", fname)
|
|
||||||
scanner := bufio.NewScanner(corpus)
|
|
||||||
scanner.Buffer(make([]byte, 1024), 10*1024*1024)
|
|
||||||
for scanner.Scan() {
|
|
||||||
s := scanner.Text()
|
|
||||||
if len(s) >= 2 && strings.HasPrefix(s, "0x") {
|
|
||||||
s = s[2:]
|
|
||||||
}
|
|
||||||
b, err := hex.DecodeString(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(err) // rotten corpus
|
|
||||||
}
|
|
||||||
f.Add(b)
|
|
||||||
}
|
|
||||||
corpus.Close()
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
panic(err) // rotten corpus
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// And do the fuzzing
|
|
||||||
f.Fuzz(func(t *testing.T, data []byte) {
|
|
||||||
var (
|
|
||||||
jt = vm.NewPragueEOFInstructionSetForTesting()
|
|
||||||
c vm.Container
|
|
||||||
)
|
|
||||||
cpy := common.CopyBytes(data)
|
|
||||||
if err := c.UnmarshalBinary(data, true); err == nil {
|
|
||||||
c.ValidateCode(&jt, true)
|
|
||||||
if have := c.MarshalBinary(); !bytes.Equal(have, data) {
|
|
||||||
t.Fatal("Unmarshal-> Marshal failure!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := c.UnmarshalBinary(data, false); err == nil {
|
|
||||||
c.ValidateCode(&jt, false)
|
|
||||||
if have := c.MarshalBinary(); !bytes.Equal(have, data) {
|
|
||||||
t.Fatal("Unmarshal-> Marshal failure!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !bytes.Equal(cpy, data) {
|
|
||||||
panic("data modified during unmarshalling")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEofParseInitcode(t *testing.T) {
|
|
||||||
testEofParse(t, true, "testdata/eof/results.initcode.txt")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEofParseRegular(t *testing.T) {
|
|
||||||
testEofParse(t, false, "testdata/eof/results.regular.txt")
|
|
||||||
}
|
|
||||||
|
|
||||||
func testEofParse(t *testing.T, isInitCode bool, wantFile string) {
|
|
||||||
var wantFn func() string
|
|
||||||
var wantLoc = 0
|
|
||||||
{ // Configure the want-reader
|
|
||||||
wants, err := os.Open(wantFile)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
scanner := bufio.NewScanner(wants)
|
|
||||||
scanner.Buffer(make([]byte, 1024), 10*1024*1024)
|
|
||||||
wantFn = func() string {
|
|
||||||
if scanner.Scan() {
|
|
||||||
wantLoc++
|
|
||||||
return scanner.Text()
|
|
||||||
}
|
|
||||||
return "end of file reached"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
fname := fmt.Sprintf("testdata/eof/eof_corpus_%d.txt", i)
|
|
||||||
corpus, err := os.Open(fname)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
t.Logf("# Reading seed data from %v", fname)
|
|
||||||
scanner := bufio.NewScanner(corpus)
|
|
||||||
scanner.Buffer(make([]byte, 1024), 10*1024*1024)
|
|
||||||
line := 1
|
|
||||||
for scanner.Scan() {
|
|
||||||
s := scanner.Text()
|
|
||||||
if len(s) >= 2 && strings.HasPrefix(s, "0x") {
|
|
||||||
s = s[2:]
|
|
||||||
}
|
|
||||||
b, err := hex.DecodeString(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(err) // rotten corpus
|
|
||||||
}
|
|
||||||
have := "OK"
|
|
||||||
if _, err := parse(b, isInitCode); err != nil {
|
|
||||||
have = fmt.Sprintf("ERR: %v", err)
|
|
||||||
}
|
|
||||||
if false { // Change this to generate the want-output
|
|
||||||
fmt.Printf("%v\n", have)
|
|
||||||
} else {
|
|
||||||
want := wantFn()
|
|
||||||
if have != want {
|
|
||||||
if len(want) > 100 {
|
|
||||||
want = want[:100]
|
|
||||||
}
|
|
||||||
if len(b) > 100 {
|
|
||||||
b = b[:100]
|
|
||||||
}
|
|
||||||
t.Errorf("%v:%d\n%v\ninput %x\nisInit: %v\nhave: %q\nwant: %q\n",
|
|
||||||
fname, line, fmt.Sprintf("%v:%d", wantFile, wantLoc), b, isInitCode, have, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
line++
|
|
||||||
}
|
|
||||||
corpus.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEofParse(b *testing.B) {
|
|
||||||
corpus, err := os.Open("testdata/eof/eof_benches.txt")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
defer corpus.Close()
|
|
||||||
scanner := bufio.NewScanner(corpus)
|
|
||||||
scanner.Buffer(make([]byte, 1024), 10*1024*1024)
|
|
||||||
line := 1
|
|
||||||
for scanner.Scan() {
|
|
||||||
s := scanner.Text()
|
|
||||||
if len(s) >= 2 && strings.HasPrefix(s, "0x") {
|
|
||||||
s = s[2:]
|
|
||||||
}
|
|
||||||
data, err := hex.DecodeString(s)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err) // rotten corpus
|
|
||||||
}
|
|
||||||
b.Run(fmt.Sprintf("test-%d", line), func(b *testing.B) {
|
|
||||||
b.ReportAllocs()
|
|
||||||
b.SetBytes(int64(len(data)))
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, _ = parse(data, false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
line++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,7 +23,6 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
@@ -51,8 +50,6 @@ type Prestate struct {
|
|||||||
Pre types.GenesisAlloc `json:"pre"`
|
Pre types.GenesisAlloc `json:"pre"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type ExecutionResult -field-override executionResultMarshaling -out gen_execresult.go
|
|
||||||
|
|
||||||
// ExecutionResult contains the execution status after running a state test, any
|
// ExecutionResult contains the execution status after running a state test, any
|
||||||
// error that might have occurred and a dump of the final state if requested.
|
// error that might have occurred and a dump of the final state if requested.
|
||||||
type ExecutionResult struct {
|
type ExecutionResult struct {
|
||||||
@@ -69,12 +66,8 @@ type ExecutionResult struct {
|
|||||||
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
||||||
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
||||||
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
||||||
RequestsHash *common.Hash `json:"requestsHash,omitempty"`
|
RequestsHash *common.Hash `json:"requestsRoot,omitempty"`
|
||||||
Requests [][]byte `json:"requests,omitempty"`
|
DepositRequests *types.Deposits `json:"depositRequests,omitempty"`
|
||||||
}
|
|
||||||
|
|
||||||
type executionResultMarshaling struct {
|
|
||||||
Requests []hexutil.Bytes `json:"requests,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ommer struct {
|
type ommer struct {
|
||||||
@@ -132,7 +125,7 @@ type rejectedTx struct {
|
|||||||
// Apply applies a set of transactions to a pre-state
|
// Apply applies a set of transactions to a pre-state
|
||||||
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
txIt txIterator, miningReward int64,
|
txIt txIterator, miningReward int64,
|
||||||
getTracerFn func(txIndex int, txHash common.Hash, chainConfig *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error)) (*state.StateDB, *ExecutionResult, []byte, error) {
|
getTracerFn func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error)) (*state.StateDB, *ExecutionResult, []byte, error) {
|
||||||
// Capture errors for BLOCKHASH operation, if we haven't been supplied the
|
// Capture errors for BLOCKHASH operation, if we haven't been supplied the
|
||||||
// required blockhashes
|
// required blockhashes
|
||||||
var hashError error
|
var hashError error
|
||||||
@@ -242,7 +235,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tracer, traceOutput, err := getTracerFn(txIndex, tx.Hash(), chainConfig)
|
tracer, traceOutput, err := getTracerFn(txIndex, tx.Hash())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -361,28 +354,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
|
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
|
||||||
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)
|
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gather the execution-layer triggered requests.
|
|
||||||
var requests [][]byte
|
|
||||||
if chainConfig.IsPrague(vmContext.BlockNumber, vmContext.Time) {
|
|
||||||
// EIP-6110 deposits
|
|
||||||
var allLogs []*types.Log
|
|
||||||
for _, receipt := range receipts {
|
|
||||||
allLogs = append(allLogs, receipt.Logs...)
|
|
||||||
}
|
|
||||||
depositRequests, err := core.ParseDepositLogs(allLogs, chainConfig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
|
|
||||||
}
|
|
||||||
requests = append(requests, depositRequests)
|
|
||||||
// create EVM for system calls
|
|
||||||
vmenv := vm.NewEVM(vmContext, vm.TxContext{}, statedb, chainConfig, vm.Config{})
|
|
||||||
// EIP-7002 withdrawals
|
|
||||||
requests = append(requests, core.ProcessWithdrawalQueue(vmenv, statedb))
|
|
||||||
// EIP-7251 consolidations
|
|
||||||
requests = append(requests, core.ProcessConsolidationQueue(vmenv, statedb))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit block
|
// Commit block
|
||||||
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
|
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -408,17 +379,28 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
|
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
|
||||||
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
||||||
}
|
}
|
||||||
if requests != nil {
|
if chainConfig.IsPrague(vmContext.BlockNumber, vmContext.Time) {
|
||||||
// Set requestsHash on block.
|
// Parse the requests from the logs
|
||||||
h := types.CalcRequestsHash(requests)
|
var allLogs []*types.Log
|
||||||
execRs.RequestsHash = &h
|
for _, receipt := range receipts {
|
||||||
for i := range requests {
|
allLogs = append(allLogs, receipt.Logs...)
|
||||||
// remove prefix
|
|
||||||
requests[i] = requests[i][1:]
|
|
||||||
}
|
}
|
||||||
execRs.Requests = requests
|
requests, err := core.ParseDepositLogs(allLogs, chainConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
|
||||||
|
}
|
||||||
|
// Calculate the requests root
|
||||||
|
h := types.DeriveSha(requests, trie.NewStackTrie(nil))
|
||||||
|
execRs.RequestsHash = &h
|
||||||
|
// Get the deposits from the requests
|
||||||
|
deposits := make(types.Deposits, 0)
|
||||||
|
for _, req := range requests {
|
||||||
|
if dep, ok := req.Inner().(*types.Deposit); ok {
|
||||||
|
deposits = append(deposits, dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
execRs.DepositRequests = &deposits
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-create statedb instance with new root upon the updated database
|
// Re-create statedb instance with new root upon the updated database
|
||||||
// for accessing latest states.
|
// for accessing latest states.
|
||||||
statedb, err = state.New(root, statedb.Database())
|
statedb, err = state.New(root, statedb.Database())
|
||||||
|
|||||||
@@ -1,134 +0,0 @@
|
|||||||
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
|
||||||
|
|
||||||
package t8ntool
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = (*executionResultMarshaling)(nil)
|
|
||||||
|
|
||||||
// MarshalJSON marshals as JSON.
|
|
||||||
func (e ExecutionResult) MarshalJSON() ([]byte, error) {
|
|
||||||
type ExecutionResult struct {
|
|
||||||
StateRoot common.Hash `json:"stateRoot"`
|
|
||||||
TxRoot common.Hash `json:"txRoot"`
|
|
||||||
ReceiptRoot common.Hash `json:"receiptsRoot"`
|
|
||||||
LogsHash common.Hash `json:"logsHash"`
|
|
||||||
Bloom types.Bloom `json:"logsBloom" gencodec:"required"`
|
|
||||||
Receipts types.Receipts `json:"receipts"`
|
|
||||||
Rejected []*rejectedTx `json:"rejected,omitempty"`
|
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
|
||||||
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
|
||||||
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
|
||||||
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
|
||||||
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
|
||||||
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
|
||||||
RequestsHash *common.Hash `json:"requestsHash,omitempty"`
|
|
||||||
Requests []hexutil.Bytes `json:"requests,omitempty"`
|
|
||||||
}
|
|
||||||
var enc ExecutionResult
|
|
||||||
enc.StateRoot = e.StateRoot
|
|
||||||
enc.TxRoot = e.TxRoot
|
|
||||||
enc.ReceiptRoot = e.ReceiptRoot
|
|
||||||
enc.LogsHash = e.LogsHash
|
|
||||||
enc.Bloom = e.Bloom
|
|
||||||
enc.Receipts = e.Receipts
|
|
||||||
enc.Rejected = e.Rejected
|
|
||||||
enc.Difficulty = e.Difficulty
|
|
||||||
enc.GasUsed = e.GasUsed
|
|
||||||
enc.BaseFee = e.BaseFee
|
|
||||||
enc.WithdrawalsRoot = e.WithdrawalsRoot
|
|
||||||
enc.CurrentExcessBlobGas = e.CurrentExcessBlobGas
|
|
||||||
enc.CurrentBlobGasUsed = e.CurrentBlobGasUsed
|
|
||||||
enc.RequestsHash = e.RequestsHash
|
|
||||||
if e.Requests != nil {
|
|
||||||
enc.Requests = make([]hexutil.Bytes, len(e.Requests))
|
|
||||||
for k, v := range e.Requests {
|
|
||||||
enc.Requests[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return json.Marshal(&enc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals from JSON.
|
|
||||||
func (e *ExecutionResult) UnmarshalJSON(input []byte) error {
|
|
||||||
type ExecutionResult struct {
|
|
||||||
StateRoot *common.Hash `json:"stateRoot"`
|
|
||||||
TxRoot *common.Hash `json:"txRoot"`
|
|
||||||
ReceiptRoot *common.Hash `json:"receiptsRoot"`
|
|
||||||
LogsHash *common.Hash `json:"logsHash"`
|
|
||||||
Bloom *types.Bloom `json:"logsBloom" gencodec:"required"`
|
|
||||||
Receipts *types.Receipts `json:"receipts"`
|
|
||||||
Rejected []*rejectedTx `json:"rejected,omitempty"`
|
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
|
||||||
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
|
|
||||||
BaseFee *math.HexOrDecimal256 `json:"currentBaseFee,omitempty"`
|
|
||||||
WithdrawalsRoot *common.Hash `json:"withdrawalsRoot,omitempty"`
|
|
||||||
CurrentExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas,omitempty"`
|
|
||||||
CurrentBlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed,omitempty"`
|
|
||||||
RequestsHash *common.Hash `json:"requestsHash,omitempty"`
|
|
||||||
Requests []hexutil.Bytes `json:"requests,omitempty"`
|
|
||||||
}
|
|
||||||
var dec ExecutionResult
|
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if dec.StateRoot != nil {
|
|
||||||
e.StateRoot = *dec.StateRoot
|
|
||||||
}
|
|
||||||
if dec.TxRoot != nil {
|
|
||||||
e.TxRoot = *dec.TxRoot
|
|
||||||
}
|
|
||||||
if dec.ReceiptRoot != nil {
|
|
||||||
e.ReceiptRoot = *dec.ReceiptRoot
|
|
||||||
}
|
|
||||||
if dec.LogsHash != nil {
|
|
||||||
e.LogsHash = *dec.LogsHash
|
|
||||||
}
|
|
||||||
if dec.Bloom == nil {
|
|
||||||
return errors.New("missing required field 'logsBloom' for ExecutionResult")
|
|
||||||
}
|
|
||||||
e.Bloom = *dec.Bloom
|
|
||||||
if dec.Receipts != nil {
|
|
||||||
e.Receipts = *dec.Receipts
|
|
||||||
}
|
|
||||||
if dec.Rejected != nil {
|
|
||||||
e.Rejected = dec.Rejected
|
|
||||||
}
|
|
||||||
if dec.Difficulty == nil {
|
|
||||||
return errors.New("missing required field 'currentDifficulty' for ExecutionResult")
|
|
||||||
}
|
|
||||||
e.Difficulty = dec.Difficulty
|
|
||||||
if dec.GasUsed != nil {
|
|
||||||
e.GasUsed = *dec.GasUsed
|
|
||||||
}
|
|
||||||
if dec.BaseFee != nil {
|
|
||||||
e.BaseFee = dec.BaseFee
|
|
||||||
}
|
|
||||||
if dec.WithdrawalsRoot != nil {
|
|
||||||
e.WithdrawalsRoot = dec.WithdrawalsRoot
|
|
||||||
}
|
|
||||||
if dec.CurrentExcessBlobGas != nil {
|
|
||||||
e.CurrentExcessBlobGas = dec.CurrentExcessBlobGas
|
|
||||||
}
|
|
||||||
if dec.CurrentBlobGasUsed != nil {
|
|
||||||
e.CurrentBlobGasUsed = dec.CurrentBlobGasUsed
|
|
||||||
}
|
|
||||||
if dec.RequestsHash != nil {
|
|
||||||
e.RequestsHash = dec.RequestsHash
|
|
||||||
}
|
|
||||||
if dec.Requests != nil {
|
|
||||||
e.Requests = make([][]byte, len(dec.Requests))
|
|
||||||
for k, v := range dec.Requests {
|
|
||||||
e.Requests[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -82,9 +82,7 @@ type input struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Transition(ctx *cli.Context) error {
|
func Transition(ctx *cli.Context) error {
|
||||||
var getTracer = func(txIndex int, txHash common.Hash, chainConfig *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error) {
|
var getTracer = func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) { return nil, nil, nil }
|
||||||
return nil, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
baseDir, err := createBasedir(ctx)
|
baseDir, err := createBasedir(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -99,7 +97,7 @@ func Transition(ctx *cli.Context) error {
|
|||||||
EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name),
|
EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name),
|
||||||
Debug: true,
|
Debug: true,
|
||||||
}
|
}
|
||||||
getTracer = func(txIndex int, txHash common.Hash, _ *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error) {
|
getTracer = func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String())))
|
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String())))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
||||||
@@ -123,12 +121,12 @@ func Transition(ctx *cli.Context) error {
|
|||||||
if ctx.IsSet(TraceTracerConfigFlag.Name) {
|
if ctx.IsSet(TraceTracerConfigFlag.Name) {
|
||||||
config = []byte(ctx.String(TraceTracerConfigFlag.Name))
|
config = []byte(ctx.String(TraceTracerConfigFlag.Name))
|
||||||
}
|
}
|
||||||
getTracer = func(txIndex int, txHash common.Hash, chainConfig *params.ChainConfig) (*tracers.Tracer, io.WriteCloser, error) {
|
getTracer = func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.json", txIndex, txHash.String())))
|
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.json", txIndex, txHash.String())))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
||||||
}
|
}
|
||||||
tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), nil, config, chainConfig)
|
tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), nil, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %w", err))
|
return nil, nil, NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %w", err))
|
||||||
}
|
}
|
||||||
|
|||||||
136
cmd/evm/main.go
136
cmd/evm/main.go
@@ -21,7 +21,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
|
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
|
||||||
"github.com/ethereum/go-ethereum/internal/debug"
|
"github.com/ethereum/go-ethereum/internal/debug"
|
||||||
@@ -139,90 +138,61 @@ var (
|
|||||||
Usage: "enable return data output",
|
Usage: "enable return data output",
|
||||||
Category: flags.VMCategory,
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
refTestFlag = &cli.StringFlag{
|
|
||||||
Name: "test",
|
|
||||||
Usage: "Path to EOF validation reference test.",
|
|
||||||
}
|
|
||||||
hexFlag = &cli.StringFlag{
|
|
||||||
Name: "hex",
|
|
||||||
Usage: "single container data parse and validation",
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var stateTransitionCommand = &cli.Command{
|
||||||
stateTransitionCommand = &cli.Command{
|
Name: "transition",
|
||||||
Name: "transition",
|
Aliases: []string{"t8n"},
|
||||||
Aliases: []string{"t8n"},
|
Usage: "Executes a full state transition",
|
||||||
Usage: "Executes a full state transition",
|
Action: t8ntool.Transition,
|
||||||
Action: t8ntool.Transition,
|
Flags: []cli.Flag{
|
||||||
Flags: []cli.Flag{
|
t8ntool.TraceFlag,
|
||||||
t8ntool.TraceFlag,
|
t8ntool.TraceTracerFlag,
|
||||||
t8ntool.TraceTracerFlag,
|
t8ntool.TraceTracerConfigFlag,
|
||||||
t8ntool.TraceTracerConfigFlag,
|
t8ntool.TraceEnableMemoryFlag,
|
||||||
t8ntool.TraceEnableMemoryFlag,
|
t8ntool.TraceDisableStackFlag,
|
||||||
t8ntool.TraceDisableStackFlag,
|
t8ntool.TraceEnableReturnDataFlag,
|
||||||
t8ntool.TraceEnableReturnDataFlag,
|
t8ntool.TraceEnableCallFramesFlag,
|
||||||
t8ntool.TraceEnableCallFramesFlag,
|
t8ntool.OutputBasedir,
|
||||||
t8ntool.OutputBasedir,
|
t8ntool.OutputAllocFlag,
|
||||||
t8ntool.OutputAllocFlag,
|
t8ntool.OutputResultFlag,
|
||||||
t8ntool.OutputResultFlag,
|
t8ntool.OutputBodyFlag,
|
||||||
t8ntool.OutputBodyFlag,
|
t8ntool.InputAllocFlag,
|
||||||
t8ntool.InputAllocFlag,
|
t8ntool.InputEnvFlag,
|
||||||
t8ntool.InputEnvFlag,
|
t8ntool.InputTxsFlag,
|
||||||
t8ntool.InputTxsFlag,
|
t8ntool.ForknameFlag,
|
||||||
t8ntool.ForknameFlag,
|
t8ntool.ChainIDFlag,
|
||||||
t8ntool.ChainIDFlag,
|
t8ntool.RewardFlag,
|
||||||
t8ntool.RewardFlag,
|
},
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
transactionCommand = &cli.Command{
|
var transactionCommand = &cli.Command{
|
||||||
Name: "transaction",
|
Name: "transaction",
|
||||||
Aliases: []string{"t9n"},
|
Aliases: []string{"t9n"},
|
||||||
Usage: "Performs transaction validation",
|
Usage: "Performs transaction validation",
|
||||||
Action: t8ntool.Transaction,
|
Action: t8ntool.Transaction,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
t8ntool.InputTxsFlag,
|
t8ntool.InputTxsFlag,
|
||||||
t8ntool.ChainIDFlag,
|
t8ntool.ChainIDFlag,
|
||||||
t8ntool.ForknameFlag,
|
t8ntool.ForknameFlag,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
blockBuilderCommand = &cli.Command{
|
var blockBuilderCommand = &cli.Command{
|
||||||
Name: "block-builder",
|
Name: "block-builder",
|
||||||
Aliases: []string{"b11r"},
|
Aliases: []string{"b11r"},
|
||||||
Usage: "Builds a block",
|
Usage: "Builds a block",
|
||||||
Action: t8ntool.BuildBlock,
|
Action: t8ntool.BuildBlock,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
t8ntool.OutputBasedir,
|
t8ntool.OutputBasedir,
|
||||||
t8ntool.OutputBlockFlag,
|
t8ntool.OutputBlockFlag,
|
||||||
t8ntool.InputHeaderFlag,
|
t8ntool.InputHeaderFlag,
|
||||||
t8ntool.InputOmmersFlag,
|
t8ntool.InputOmmersFlag,
|
||||||
t8ntool.InputWithdrawalsFlag,
|
t8ntool.InputWithdrawalsFlag,
|
||||||
t8ntool.InputTxsRlpFlag,
|
t8ntool.InputTxsRlpFlag,
|
||||||
t8ntool.SealCliqueFlag,
|
t8ntool.SealCliqueFlag,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
eofParseCommand = &cli.Command{
|
|
||||||
Name: "eofparse",
|
|
||||||
Aliases: []string{"eof"},
|
|
||||||
Usage: "Parses hex eof container and returns validation errors (if any)",
|
|
||||||
Action: eofParseAction,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
hexFlag,
|
|
||||||
refTestFlag,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
eofDumpCommand = &cli.Command{
|
|
||||||
Name: "eofdump",
|
|
||||||
Usage: "Parses hex eof container and prints out human-readable representation of the container.",
|
|
||||||
Action: eofDumpAction,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
hexFlag,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// vmFlags contains flags related to running the EVM.
|
// vmFlags contains flags related to running the EVM.
|
||||||
var vmFlags = []cli.Flag{
|
var vmFlags = []cli.Flag{
|
||||||
@@ -255,7 +225,7 @@ var traceFlags = []cli.Flag{
|
|||||||
var app = flags.NewApp("the evm command line interface")
|
var app = flags.NewApp("the evm command line interface")
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
app.Flags = slices.Concat(vmFlags, traceFlags, debug.Flags)
|
app.Flags = flags.Merge(vmFlags, traceFlags, debug.Flags)
|
||||||
app.Commands = []*cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
compileCommand,
|
compileCommand,
|
||||||
disasmCommand,
|
disasmCommand,
|
||||||
@@ -265,8 +235,6 @@ func init() {
|
|||||||
stateTransitionCommand,
|
stateTransitionCommand,
|
||||||
transactionCommand,
|
transactionCommand,
|
||||||
blockBuilderCommand,
|
blockBuilderCommand,
|
||||||
eofParseCommand,
|
|
||||||
eofDumpCommand,
|
|
||||||
}
|
}
|
||||||
app.Before = func(ctx *cli.Context) error {
|
app.Before = func(ctx *cli.Context) error {
|
||||||
flags.MigrateGlobalFlags(ctx)
|
flags.MigrateGlobalFlags(ctx)
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
"slices"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -51,7 +50,7 @@ var runCommand = &cli.Command{
|
|||||||
Usage: "Run arbitrary evm binary",
|
Usage: "Run arbitrary evm binary",
|
||||||
ArgsUsage: "<code>",
|
ArgsUsage: "<code>",
|
||||||
Description: `The run command runs arbitrary EVM code.`,
|
Description: `The run command runs arbitrary EVM code.`,
|
||||||
Flags: slices.Concat(vmFlags, traceFlags),
|
Flags: flags.Merge(vmFlags, traceFlags),
|
||||||
}
|
}
|
||||||
|
|
||||||
// readGenesis will read the given JSON format genesis file and return
|
// readGenesis will read the given JSON format genesis file and return
|
||||||
|
|||||||
@@ -524,7 +524,7 @@ func TestT9n(t *testing.T) {
|
|||||||
ok, err := cmpJson(have, want)
|
ok, err := cmpJson(have, want)
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
t.Log(string(have))
|
t.Logf(string(have))
|
||||||
t.Fatalf("test %d, json parsing failed: %v", i, err)
|
t.Fatalf("test %d, json parsing failed: %v", i, err)
|
||||||
case !ok:
|
case !ok:
|
||||||
t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want))
|
t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want))
|
||||||
@@ -659,7 +659,7 @@ func TestB11r(t *testing.T) {
|
|||||||
ok, err := cmpJson(have, want)
|
ok, err := cmpJson(have, want)
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
t.Log(string(have))
|
t.Logf(string(have))
|
||||||
t.Fatalf("test %d, json parsing failed: %v", i, err)
|
t.Fatalf("test %d, json parsing failed: %v", i, err)
|
||||||
case !ok:
|
case !ok:
|
||||||
t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want))
|
t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want))
|
||||||
|
|||||||
19
cmd/evm/testdata/eof/eof_benches.txt
vendored
19
cmd/evm/testdata/eof/eof_benches.txt
vendored
File diff suppressed because one or more lines are too long
1986
cmd/evm/testdata/eof/eof_corpus_0.txt
vendored
1986
cmd/evm/testdata/eof/eof_corpus_0.txt
vendored
File diff suppressed because one or more lines are too long
350
cmd/evm/testdata/eof/eof_corpus_1.txt
vendored
350
cmd/evm/testdata/eof/eof_corpus_1.txt
vendored
File diff suppressed because one or more lines are too long
2336
cmd/evm/testdata/eof/results.initcode.txt
vendored
2336
cmd/evm/testdata/eof/results.initcode.txt
vendored
File diff suppressed because it is too large
Load Diff
2336
cmd/evm/testdata/eof/results.regular.txt
vendored
2336
cmd/evm/testdata/eof/results.regular.txt
vendored
File diff suppressed because it is too large
Load Diff
@@ -113,6 +113,7 @@ func TestAccountImport(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
test := test
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
importAccountWithExpect(t, test.key, test.output)
|
importAccountWithExpect(t, test.key, test.output)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"slices"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -37,6 +36,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/internal/era"
|
"github.com/ethereum/go-ethereum/internal/era"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
@@ -49,7 +49,7 @@ var (
|
|||||||
Name: "init",
|
Name: "init",
|
||||||
Usage: "Bootstrap and initialize a new genesis block",
|
Usage: "Bootstrap and initialize a new genesis block",
|
||||||
ArgsUsage: "<genesisPath>",
|
ArgsUsage: "<genesisPath>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.CachePreimagesFlag,
|
utils.CachePreimagesFlag,
|
||||||
utils.OverrideCancun,
|
utils.OverrideCancun,
|
||||||
utils.OverrideVerkle,
|
utils.OverrideVerkle,
|
||||||
@@ -76,7 +76,7 @@ if one is set. Otherwise it prints the genesis from the datadir.`,
|
|||||||
Name: "import",
|
Name: "import",
|
||||||
Usage: "Import a blockchain file",
|
Usage: "Import a blockchain file",
|
||||||
ArgsUsage: "<filename> (<filename 2> ... <filename N>) ",
|
ArgsUsage: "<filename> (<filename 2> ... <filename N>) ",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
utils.GCModeFlag,
|
utils.GCModeFlag,
|
||||||
@@ -115,7 +115,7 @@ processing will proceed even if an individual RLP-file import failure occurs.`,
|
|||||||
Name: "export",
|
Name: "export",
|
||||||
Usage: "Export blockchain into file",
|
Usage: "Export blockchain into file",
|
||||||
ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]",
|
ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.DatabaseFlags),
|
}, utils.DatabaseFlags),
|
||||||
@@ -131,7 +131,7 @@ be gzipped.`,
|
|||||||
Name: "import-history",
|
Name: "import-history",
|
||||||
Usage: "Import an Era archive",
|
Usage: "Import an Era archive",
|
||||||
ArgsUsage: "<dir>",
|
ArgsUsage: "<dir>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.TxLookupLimitFlag,
|
utils.TxLookupLimitFlag,
|
||||||
},
|
},
|
||||||
utils.DatabaseFlags,
|
utils.DatabaseFlags,
|
||||||
@@ -147,7 +147,7 @@ from Era archives.
|
|||||||
Name: "export-history",
|
Name: "export-history",
|
||||||
Usage: "Export blockchain history to Era archives",
|
Usage: "Export blockchain history to Era archives",
|
||||||
ArgsUsage: "<dir> <first> <last>",
|
ArgsUsage: "<dir> <first> <last>",
|
||||||
Flags: slices.Concat(utils.DatabaseFlags),
|
Flags: flags.Merge(utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The export-history command will export blocks and their corresponding receipts
|
The export-history command will export blocks and their corresponding receipts
|
||||||
into Era archives. Eras are typically packaged in steps of 8192 blocks.
|
into Era archives. Eras are typically packaged in steps of 8192 blocks.
|
||||||
@@ -158,7 +158,7 @@ into Era archives. Eras are typically packaged in steps of 8192 blocks.
|
|||||||
Name: "import-preimages",
|
Name: "import-preimages",
|
||||||
Usage: "Import the preimage database from an RLP stream",
|
Usage: "Import the preimage database from an RLP stream",
|
||||||
ArgsUsage: "<datafile>",
|
ArgsUsage: "<datafile>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.DatabaseFlags),
|
}, utils.DatabaseFlags),
|
||||||
@@ -173,7 +173,7 @@ It's deprecated, please use "geth db import" instead.
|
|||||||
Name: "dump",
|
Name: "dump",
|
||||||
Usage: "Dump a specific block from storage",
|
Usage: "Dump a specific block from storage",
|
||||||
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.IterativeOutputFlag,
|
utils.IterativeOutputFlag,
|
||||||
utils.ExcludeCodeFlag,
|
utils.ExcludeCodeFlag,
|
||||||
@@ -221,23 +221,22 @@ func initGenesis(ctx *cli.Context) error {
|
|||||||
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
v := ctx.Uint64(utils.OverrideVerkle.Name)
|
||||||
overrides.OverrideVerkle = &v
|
overrides.OverrideVerkle = &v
|
||||||
}
|
}
|
||||||
|
for _, name := range []string{"chaindata", "lightchaindata"} {
|
||||||
|
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.String(utils.AncientFlag.Name), "", false)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to open database: %v", err)
|
||||||
|
}
|
||||||
|
defer chaindb.Close()
|
||||||
|
|
||||||
chaindb, err := stack.OpenDatabaseWithFreezer("chaindata", 0, 0, ctx.String(utils.AncientFlag.Name), "", false)
|
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
|
||||||
if err != nil {
|
defer triedb.Close()
|
||||||
utils.Fatalf("Failed to open database: %v", err)
|
|
||||||
|
_, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to write genesis block: %v", err)
|
||||||
|
}
|
||||||
|
log.Info("Successfully wrote genesis state", "database", name, "hash", hash)
|
||||||
}
|
}
|
||||||
defer chaindb.Close()
|
|
||||||
|
|
||||||
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
|
|
||||||
defer triedb.Close()
|
|
||||||
|
|
||||||
_, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
|
||||||
if err != nil {
|
|
||||||
utils.Fatalf("Failed to write genesis block: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info("Successfully wrote genesis state", "database", "chaindata", "hash", hash)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,22 +258,29 @@ func dumpGenesis(ctx *cli.Context) error {
|
|||||||
|
|
||||||
// dump whatever already exists in the datadir
|
// dump whatever already exists in the datadir
|
||||||
stack, _ := makeConfigNode(ctx)
|
stack, _ := makeConfigNode(ctx)
|
||||||
|
for _, name := range []string{"chaindata", "lightchaindata"} {
|
||||||
|
db, err := stack.OpenDatabase(name, 0, 0, "", true)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
genesis, err := core.ReadGenesis(db)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("failed to read genesis: %s", err)
|
||||||
|
}
|
||||||
|
db.Close()
|
||||||
|
|
||||||
db, err := stack.OpenDatabase("chaindata", 0, 0, "", true)
|
if err := json.NewEncoder(os.Stdout).Encode(*genesis); err != nil {
|
||||||
if err != nil {
|
utils.Fatalf("could not encode stored genesis: %s", err)
|
||||||
return err
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
defer db.Close()
|
if ctx.IsSet(utils.DataDirFlag.Name) {
|
||||||
|
utils.Fatalf("no existing datadir at %s", stack.Config().DataDir)
|
||||||
genesis, err = core.ReadGenesis(db)
|
|
||||||
if err != nil {
|
|
||||||
utils.Fatalf("failed to read genesis: %s", err)
|
|
||||||
}
|
}
|
||||||
|
utils.Fatalf("no network preset provided, and no genesis exists in the default datadir")
|
||||||
if err := json.NewEncoder(os.Stdout).Encode(*genesis); err != nil {
|
|
||||||
utils.Fatalf("could not encode stored genesis: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,7 +557,7 @@ func parseDumpConfig(ctx *cli.Context, db ethdb.Database) (*state.DumpConfig, co
|
|||||||
default:
|
default:
|
||||||
return nil, common.Hash{}, fmt.Errorf("invalid start argument: %x. 20 or 32 hex-encoded bytes required", startArg)
|
return nil, common.Hash{}, fmt.Errorf("invalid start argument: %x. 20 or 32 hex-encoded bytes required", startArg)
|
||||||
}
|
}
|
||||||
conf := &state.DumpConfig{
|
var conf = &state.DumpConfig{
|
||||||
SkipCode: ctx.Bool(utils.ExcludeCodeFlag.Name),
|
SkipCode: ctx.Bool(utils.ExcludeCodeFlag.Name),
|
||||||
SkipStorage: ctx.Bool(utils.ExcludeStorageFlag.Name),
|
SkipStorage: ctx.Bool(utils.ExcludeStorageFlag.Name),
|
||||||
OnlyWithAddresses: !ctx.Bool(utils.IncludeIncompletesFlag.Name),
|
OnlyWithAddresses: !ctx.Bool(utils.IncludeIncompletesFlag.Name),
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"slices"
|
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
@@ -43,6 +42,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/naoina/toml"
|
"github.com/naoina/toml"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
@@ -54,7 +54,7 @@ var (
|
|||||||
Name: "dumpconfig",
|
Name: "dumpconfig",
|
||||||
Usage: "Export configuration values in a TOML format",
|
Usage: "Export configuration values in a TOML format",
|
||||||
ArgsUsage: "<dumpfile (optional)>",
|
ArgsUsage: "<dumpfile (optional)>",
|
||||||
Flags: slices.Concat(nodeFlags, rpcFlags),
|
Flags: flags.Merge(nodeFlags, rpcFlags),
|
||||||
Description: `Export configuration values in TOML format (to stdout by default).`,
|
Description: `Export configuration values in TOML format (to stdout by default).`,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,10 +130,10 @@ func defaultNodeConfig() node.Config {
|
|||||||
git, _ := version.VCS()
|
git, _ := version.VCS()
|
||||||
cfg := node.DefaultConfig
|
cfg := node.DefaultConfig
|
||||||
cfg.Name = clientIdentifier
|
cfg.Name = clientIdentifier
|
||||||
cfg.Version = version.WithCommit(git.Commit, git.Date)
|
cfg.Version = params.VersionWithCommit(git.Commit, git.Date)
|
||||||
cfg.HTTPModules = append(cfg.HTTPModules, "eth")
|
cfg.HTTPModules = append(cfg.HTTPModules, "eth")
|
||||||
cfg.WSModules = append(cfg.WSModules, "eth")
|
cfg.WSModules = append(cfg.WSModules, "eth")
|
||||||
cfg.IPCPath = clientIdentifier + ".ipc"
|
cfg.IPCPath = "geth.ipc"
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ var (
|
|||||||
Action: localConsole,
|
Action: localConsole,
|
||||||
Name: "console",
|
Name: "console",
|
||||||
Usage: "Start an interactive JavaScript environment",
|
Usage: "Start an interactive JavaScript environment",
|
||||||
Flags: slices.Concat(nodeFlags, rpcFlags, consoleFlags),
|
Flags: flags.Merge(nodeFlags, rpcFlags, consoleFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The Geth console is an interactive shell for the JavaScript runtime environment
|
The Geth console is an interactive shell for the JavaScript runtime environment
|
||||||
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
||||||
@@ -45,7 +45,7 @@ See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console.`,
|
|||||||
Name: "attach",
|
Name: "attach",
|
||||||
Usage: "Start an interactive JavaScript environment (connect to node)",
|
Usage: "Start an interactive JavaScript environment (connect to node)",
|
||||||
ArgsUsage: "[endpoint]",
|
ArgsUsage: "[endpoint]",
|
||||||
Flags: slices.Concat([]cli.Flag{utils.DataDirFlag, utils.HttpHeaderFlag}, consoleFlags),
|
Flags: flags.Merge([]cli.Flag{utils.DataDirFlag, utils.HttpHeaderFlag}, consoleFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The Geth console is an interactive shell for the JavaScript runtime environment
|
The Geth console is an interactive shell for the JavaScript runtime environment
|
||||||
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
which exposes a node admin interface as well as the Ðapp JavaScript API.
|
||||||
@@ -58,7 +58,7 @@ This command allows to open a console on a running geth node.`,
|
|||||||
Name: "js",
|
Name: "js",
|
||||||
Usage: "(DEPRECATED) Execute the specified JavaScript files",
|
Usage: "(DEPRECATED) Execute the specified JavaScript files",
|
||||||
ArgsUsage: "<jsfile> [jsfile...]",
|
ArgsUsage: "<jsfile> [jsfile...]",
|
||||||
Flags: slices.Concat(nodeFlags, consoleFlags),
|
Flags: flags.Merge(nodeFlags, consoleFlags),
|
||||||
Description: `
|
Description: `
|
||||||
The JavaScript VM exposes a node admin interface as well as the Ðapp
|
The JavaScript VM exposes a node admin interface as well as the Ðapp
|
||||||
JavaScript API. See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console`,
|
JavaScript API. See https://geth.ethereum.org/docs/interacting-with-geth/javascript-console`,
|
||||||
@@ -152,7 +152,7 @@ func remoteConsole(ctx *cli.Context) error {
|
|||||||
func ephemeralConsole(ctx *cli.Context) error {
|
func ephemeralConsole(ctx *cli.Context) error {
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
for _, file := range ctx.Args().Slice() {
|
for _, file := range ctx.Args().Slice() {
|
||||||
b.WriteString(fmt.Sprintf("loadScript('%s');", file))
|
b.Write([]byte(fmt.Sprintf("loadScript('%s');", file)))
|
||||||
}
|
}
|
||||||
utils.Fatalf(`The "js" command is deprecated. Please use the following instead:
|
utils.Fatalf(`The "js" command is deprecated. Please use the following instead:
|
||||||
geth --exec "%s" console`, b.String())
|
geth --exec "%s" console`, b.String())
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/internal/version"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -60,7 +60,7 @@ func TestConsoleWelcome(t *testing.T) {
|
|||||||
geth.SetTemplateFunc("goos", func() string { return runtime.GOOS })
|
geth.SetTemplateFunc("goos", func() string { return runtime.GOOS })
|
||||||
geth.SetTemplateFunc("goarch", func() string { return runtime.GOARCH })
|
geth.SetTemplateFunc("goarch", func() string { return runtime.GOARCH })
|
||||||
geth.SetTemplateFunc("gover", runtime.Version)
|
geth.SetTemplateFunc("gover", runtime.Version)
|
||||||
geth.SetTemplateFunc("gethver", func() string { return version.WithCommit("", "") })
|
geth.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
|
||||||
geth.SetTemplateFunc("niltime", func() string {
|
geth.SetTemplateFunc("niltime", func() string {
|
||||||
return time.Unix(1695902100, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
return time.Unix(1695902100, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
||||||
})
|
})
|
||||||
@@ -129,7 +129,7 @@ func testAttachWelcome(t *testing.T, geth *testgeth, endpoint, apis string) {
|
|||||||
attach.SetTemplateFunc("goos", func() string { return runtime.GOOS })
|
attach.SetTemplateFunc("goos", func() string { return runtime.GOOS })
|
||||||
attach.SetTemplateFunc("goarch", func() string { return runtime.GOARCH })
|
attach.SetTemplateFunc("goarch", func() string { return runtime.GOARCH })
|
||||||
attach.SetTemplateFunc("gover", runtime.Version)
|
attach.SetTemplateFunc("gover", runtime.Version)
|
||||||
attach.SetTemplateFunc("gethver", func() string { return version.WithCommit("", "") })
|
attach.SetTemplateFunc("gethver", func() string { return params.VersionWithCommit("", "") })
|
||||||
attach.SetTemplateFunc("niltime", func() string {
|
attach.SetTemplateFunc("niltime", func() string {
|
||||||
return time.Unix(1695902100, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
return time.Unix(1695902100, 0).Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -37,6 +36,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
@@ -60,7 +60,7 @@ var (
|
|||||||
Name: "removedb",
|
Name: "removedb",
|
||||||
Usage: "Remove blockchain and state databases",
|
Usage: "Remove blockchain and state databases",
|
||||||
ArgsUsage: "",
|
ArgsUsage: "",
|
||||||
Flags: slices.Concat(utils.DatabaseFlags,
|
Flags: flags.Merge(utils.DatabaseFlags,
|
||||||
[]cli.Flag{removeStateDataFlag, removeChainDataFlag}),
|
[]cli.Flag{removeStateDataFlag, removeChainDataFlag}),
|
||||||
Description: `
|
Description: `
|
||||||
Remove blockchain and state databases`,
|
Remove blockchain and state databases`,
|
||||||
@@ -89,7 +89,7 @@ Remove blockchain and state databases`,
|
|||||||
Action: inspect,
|
Action: inspect,
|
||||||
Name: "inspect",
|
Name: "inspect",
|
||||||
ArgsUsage: "<prefix> <start>",
|
ArgsUsage: "<prefix> <start>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Usage: "Inspect the storage size for each type of data in the database",
|
Usage: "Inspect the storage size for each type of data in the database",
|
||||||
@@ -99,7 +99,7 @@ Remove blockchain and state databases`,
|
|||||||
Action: checkStateContent,
|
Action: checkStateContent,
|
||||||
Name: "check-state-content",
|
Name: "check-state-content",
|
||||||
ArgsUsage: "<start (optional)>",
|
ArgsUsage: "<start (optional)>",
|
||||||
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Usage: "Verify that state data is cryptographically correct",
|
Usage: "Verify that state data is cryptographically correct",
|
||||||
Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes.
|
Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes.
|
||||||
For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates
|
For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates
|
||||||
@@ -109,7 +109,7 @@ a data corruption.`,
|
|||||||
Action: dbStats,
|
Action: dbStats,
|
||||||
Name: "stats",
|
Name: "stats",
|
||||||
Usage: "Print leveldb statistics",
|
Usage: "Print leveldb statistics",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ a data corruption.`,
|
|||||||
Action: dbCompact,
|
Action: dbCompact,
|
||||||
Name: "compact",
|
Name: "compact",
|
||||||
Usage: "Compact leveldb database. WARNING: May take a very long time",
|
Usage: "Compact leveldb database. WARNING: May take a very long time",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.CacheDatabaseFlag,
|
utils.CacheDatabaseFlag,
|
||||||
@@ -131,7 +131,7 @@ corruption if it is aborted during execution'!`,
|
|||||||
Name: "get",
|
Name: "get",
|
||||||
Usage: "Show the value of a database key",
|
Usage: "Show the value of a database key",
|
||||||
ArgsUsage: "<hex-encoded key>",
|
ArgsUsage: "<hex-encoded key>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "This command looks up the specified database key from the database.",
|
Description: "This command looks up the specified database key from the database.",
|
||||||
@@ -141,7 +141,7 @@ corruption if it is aborted during execution'!`,
|
|||||||
Name: "delete",
|
Name: "delete",
|
||||||
Usage: "Delete a database key (WARNING: may corrupt your database)",
|
Usage: "Delete a database key (WARNING: may corrupt your database)",
|
||||||
ArgsUsage: "<hex-encoded key>",
|
ArgsUsage: "<hex-encoded key>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `This command deletes the specified database key from the database.
|
Description: `This command deletes the specified database key from the database.
|
||||||
@@ -152,7 +152,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||||||
Name: "put",
|
Name: "put",
|
||||||
Usage: "Set the value of a database key (WARNING: may corrupt your database)",
|
Usage: "Set the value of a database key (WARNING: may corrupt your database)",
|
||||||
ArgsUsage: "<hex-encoded key> <hex-encoded value>",
|
ArgsUsage: "<hex-encoded key> <hex-encoded value>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `This command sets a given database key to the given value.
|
Description: `This command sets a given database key to the given value.
|
||||||
@@ -163,7 +163,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||||||
Name: "dumptrie",
|
Name: "dumptrie",
|
||||||
Usage: "Show the storage key/values of a given storage trie",
|
Usage: "Show the storage key/values of a given storage trie",
|
||||||
ArgsUsage: "<hex-encoded state root> <hex-encoded account hash> <hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
|
ArgsUsage: "<hex-encoded state root> <hex-encoded account hash> <hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "This command looks up the specified database key from the database.",
|
Description: "This command looks up the specified database key from the database.",
|
||||||
@@ -173,7 +173,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||||||
Name: "freezer-index",
|
Name: "freezer-index",
|
||||||
Usage: "Dump out the index of a specific freezer table",
|
Usage: "Dump out the index of a specific freezer table",
|
||||||
ArgsUsage: "<freezer-type> <table-type> <start (int)> <end (int)>",
|
ArgsUsage: "<freezer-type> <table-type> <start (int)> <end (int)>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "This command displays information about the freezer index.",
|
Description: "This command displays information about the freezer index.",
|
||||||
@@ -183,7 +183,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||||||
Name: "import",
|
Name: "import",
|
||||||
Usage: "Imports leveldb-data from an exported RLP dump.",
|
Usage: "Imports leveldb-data from an exported RLP dump.",
|
||||||
ArgsUsage: "<dumpfile> <start (optional)",
|
ArgsUsage: "<dumpfile> <start (optional)",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "The import command imports the specific chain data from an RLP encoded stream.",
|
Description: "The import command imports the specific chain data from an RLP encoded stream.",
|
||||||
@@ -193,7 +193,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||||||
Name: "export",
|
Name: "export",
|
||||||
Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.",
|
Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.",
|
||||||
ArgsUsage: "<type> <dumpfile>",
|
ArgsUsage: "<type> <dumpfile>",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.",
|
Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.",
|
||||||
@@ -202,7 +202,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||||||
Action: showMetaData,
|
Action: showMetaData,
|
||||||
Name: "metadata",
|
Name: "metadata",
|
||||||
Usage: "Shows metadata about the chain status.",
|
Usage: "Shows metadata about the chain status.",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: "Shows metadata about the chain status.",
|
Description: "Shows metadata about the chain status.",
|
||||||
@@ -212,7 +212,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||||||
Name: "inspect-history",
|
Name: "inspect-history",
|
||||||
Usage: "Inspect the state history within block range",
|
Usage: "Inspect the state history within block range",
|
||||||
ArgsUsage: "<address> [OPTIONAL <storage-slot>]",
|
ArgsUsage: "<address> [OPTIONAL <storage-slot>]",
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
&cli.Uint64Flag{
|
&cli.Uint64Flag{
|
||||||
Name: "start",
|
Name: "start",
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ var customGenesisTests = []struct {
|
|||||||
query string
|
query string
|
||||||
result string
|
result string
|
||||||
}{
|
}{
|
||||||
// Genesis file with a mostly-empty chain configuration (ensure missing fields work)
|
// Genesis file with an empty chain configuration (ensure missing fields work)
|
||||||
{
|
{
|
||||||
genesis: `{
|
genesis: `{
|
||||||
"alloc" : {},
|
"alloc" : {},
|
||||||
@@ -41,8 +41,8 @@ var customGenesisTests = []struct {
|
|||||||
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"timestamp" : "0x00",
|
"timestamp" : "0x00",
|
||||||
"config": {
|
"config" : {
|
||||||
"terminalTotalDifficulty": 0
|
"terminalTotalDifficultyPassed": true
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
query: "eth.getBlock(0).nonce",
|
query: "eth.getBlock(0).nonce",
|
||||||
@@ -64,7 +64,7 @@ var customGenesisTests = []struct {
|
|||||||
"homesteadBlock" : 42,
|
"homesteadBlock" : 42,
|
||||||
"daoForkBlock" : 141,
|
"daoForkBlock" : 141,
|
||||||
"daoForkSupport" : true,
|
"daoForkSupport" : true,
|
||||||
"terminalTotalDifficulty": 0
|
"terminalTotalDifficultyPassed" : true
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
query: "eth.getBlock(0).nonce",
|
query: "eth.getBlock(0).nonce",
|
||||||
@@ -114,8 +114,8 @@ func TestCustomBackend(t *testing.T) {
|
|||||||
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"timestamp" : "0x00",
|
"timestamp" : "0x00",
|
||||||
"config": {
|
"config" : {
|
||||||
"terminalTotalDifficulty": 0
|
"terminalTotalDifficultyPassed": true
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
type backendTest struct {
|
type backendTest struct {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -54,7 +53,7 @@ const (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// flags that configure the node
|
// flags that configure the node
|
||||||
nodeFlags = slices.Concat([]cli.Flag{
|
nodeFlags = flags.Merge([]cli.Flag{
|
||||||
utils.IdentityFlag,
|
utils.IdentityFlag,
|
||||||
utils.UnlockedAccountFlag,
|
utils.UnlockedAccountFlag,
|
||||||
utils.PasswordFileFlag,
|
utils.PasswordFileFlag,
|
||||||
@@ -67,7 +66,7 @@ var (
|
|||||||
utils.SmartCardDaemonPathFlag,
|
utils.SmartCardDaemonPathFlag,
|
||||||
utils.OverrideCancun,
|
utils.OverrideCancun,
|
||||||
utils.OverrideVerkle,
|
utils.OverrideVerkle,
|
||||||
utils.EnablePersonal, // deprecated
|
utils.EnablePersonal,
|
||||||
utils.TxPoolLocalsFlag,
|
utils.TxPoolLocalsFlag,
|
||||||
utils.TxPoolNoLocalsFlag,
|
utils.TxPoolNoLocalsFlag,
|
||||||
utils.TxPoolJournalFlag,
|
utils.TxPoolJournalFlag,
|
||||||
@@ -157,6 +156,7 @@ var (
|
|||||||
utils.BeaconGenesisRootFlag,
|
utils.BeaconGenesisRootFlag,
|
||||||
utils.BeaconGenesisTimeFlag,
|
utils.BeaconGenesisTimeFlag,
|
||||||
utils.BeaconCheckpointFlag,
|
utils.BeaconCheckpointFlag,
|
||||||
|
utils.CollectWitnessFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags)
|
}, utils.NetworkFlags, utils.DatabaseFlags)
|
||||||
|
|
||||||
rpcFlags = []cli.Flag{
|
rpcFlags = []cli.Flag{
|
||||||
@@ -252,7 +252,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
sort.Sort(cli.CommandsByName(app.Commands))
|
sort.Sort(cli.CommandsByName(app.Commands))
|
||||||
|
|
||||||
app.Flags = slices.Concat(
|
app.Flags = flags.Merge(
|
||||||
nodeFlags,
|
nodeFlags,
|
||||||
rpcFlags,
|
rpcFlags,
|
||||||
consoleFlags,
|
consoleFlags,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/internal/version"
|
"github.com/ethereum/go-ethereum/internal/version"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ func printVersion(ctx *cli.Context) error {
|
|||||||
git, _ := version.VCS()
|
git, _ := version.VCS()
|
||||||
|
|
||||||
fmt.Println(strings.Title(clientIdentifier))
|
fmt.Println(strings.Title(clientIdentifier))
|
||||||
fmt.Println("Version:", version.WithMeta)
|
fmt.Println("Version:", params.VersionWithMeta)
|
||||||
if git.Commit != "" {
|
if git.Commit != "" {
|
||||||
fmt.Println("Git Commit:", git.Commit)
|
fmt.Println("Git Commit:", git.Commit)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
@@ -33,6 +32,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
@@ -50,7 +50,7 @@ var (
|
|||||||
Usage: "Prune stale ethereum state data based on the snapshot",
|
Usage: "Prune stale ethereum state data based on the snapshot",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: pruneState,
|
Action: pruneState,
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.BloomFilterSizeFlag,
|
utils.BloomFilterSizeFlag,
|
||||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
@@ -70,7 +70,7 @@ WARNING: it's only supported in hash mode(--state.scheme=hash)".
|
|||||||
Usage: "Recalculate state hash based on the snapshot for verification",
|
Usage: "Recalculate state hash based on the snapshot for verification",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: verifyState,
|
Action: verifyState,
|
||||||
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot verify-state <state-root>
|
geth snapshot verify-state <state-root>
|
||||||
will traverse the whole accounts and storages set based on the specified
|
will traverse the whole accounts and storages set based on the specified
|
||||||
@@ -83,7 +83,7 @@ In other words, this command does the snapshot to trie conversion.
|
|||||||
Usage: "Check that there is no 'dangling' snap storage",
|
Usage: "Check that there is no 'dangling' snap storage",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: checkDanglingStorage,
|
Action: checkDanglingStorage,
|
||||||
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot check-dangling-storage <state-root> traverses the snap storage
|
geth snapshot check-dangling-storage <state-root> traverses the snap storage
|
||||||
data, and verifies that all snapshot storage data has a corresponding account.
|
data, and verifies that all snapshot storage data has a corresponding account.
|
||||||
@@ -94,7 +94,7 @@ data, and verifies that all snapshot storage data has a corresponding account.
|
|||||||
Usage: "Check all snapshot layers for the specific account",
|
Usage: "Check all snapshot layers for the specific account",
|
||||||
ArgsUsage: "<address | hash>",
|
ArgsUsage: "<address | hash>",
|
||||||
Action: checkAccount,
|
Action: checkAccount,
|
||||||
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out
|
geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out
|
||||||
information about the specified address.
|
information about the specified address.
|
||||||
@@ -105,7 +105,7 @@ information about the specified address.
|
|||||||
Usage: "Traverse the state with given root hash and perform quick verification",
|
Usage: "Traverse the state with given root hash and perform quick verification",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: traverseState,
|
Action: traverseState,
|
||||||
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot traverse-state <state-root>
|
geth snapshot traverse-state <state-root>
|
||||||
will traverse the whole state from the given state root and will abort if any
|
will traverse the whole state from the given state root and will abort if any
|
||||||
@@ -120,7 +120,7 @@ It's also usable without snapshot enabled.
|
|||||||
Usage: "Traverse the state with given root hash and perform detailed verification",
|
Usage: "Traverse the state with given root hash and perform detailed verification",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: traverseRawState,
|
Action: traverseRawState,
|
||||||
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth snapshot traverse-rawstate <state-root>
|
geth snapshot traverse-rawstate <state-root>
|
||||||
will traverse the whole state from the given root and will abort if any referenced
|
will traverse the whole state from the given root and will abort if any referenced
|
||||||
@@ -136,7 +136,7 @@ It's also usable without snapshot enabled.
|
|||||||
Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)",
|
Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)",
|
||||||
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
ArgsUsage: "[? <blockHash> | <blockNum>]",
|
||||||
Action: dumpState,
|
Action: dumpState,
|
||||||
Flags: slices.Concat([]cli.Flag{
|
Flags: flags.Merge([]cli.Flag{
|
||||||
utils.ExcludeCodeFlag,
|
utils.ExcludeCodeFlag,
|
||||||
utils.ExcludeStorageFlag,
|
utils.ExcludeStorageFlag,
|
||||||
utils.StartKeyFlag,
|
utils.StartKeyFlag,
|
||||||
@@ -428,7 +428,7 @@ func traverseRawState(ctx *cli.Context) error {
|
|||||||
log.Error("Failed to open iterator", "root", root, "err", err)
|
log.Error("Failed to open iterator", "root", root, "err", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
reader, err := triedb.NodeReader(root)
|
reader, err := triedb.Reader(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("State is non-existent", "root", root)
|
log.Error("State is non-existent", "root", root)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
2
cmd/geth/testdata/clique.json
vendored
2
cmd/geth/testdata/clique.json
vendored
@@ -8,7 +8,7 @@
|
|||||||
"byzantiumBlock": 0,
|
"byzantiumBlock": 0,
|
||||||
"constantinopleBlock": 0,
|
"constantinopleBlock": 0,
|
||||||
"petersburgBlock": 0,
|
"petersburgBlock": 0,
|
||||||
"terminalTotalDifficulty": 0,
|
"terminalTotalDifficultyPassed": true,
|
||||||
"clique": {
|
"clique": {
|
||||||
"period": 5,
|
"period": 5,
|
||||||
"epoch": 30000
|
"epoch": 30000
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-verkle"
|
"github.com/ethereum/go-verkle"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
@@ -45,7 +45,7 @@ var (
|
|||||||
Usage: "verify the conversion of a MPT into a verkle tree",
|
Usage: "verify the conversion of a MPT into a verkle tree",
|
||||||
ArgsUsage: "<root>",
|
ArgsUsage: "<root>",
|
||||||
Action: verifyVerkle,
|
Action: verifyVerkle,
|
||||||
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth verkle verify <state-root>
|
geth verkle verify <state-root>
|
||||||
This command takes a root commitment and attempts to rebuild the tree.
|
This command takes a root commitment and attempts to rebuild the tree.
|
||||||
@@ -56,7 +56,7 @@ This command takes a root commitment and attempts to rebuild the tree.
|
|||||||
Usage: "Dump a verkle tree to a DOT file",
|
Usage: "Dump a verkle tree to a DOT file",
|
||||||
ArgsUsage: "<root> <key1> [<key 2> ...]",
|
ArgsUsage: "<root> <key1> [<key 2> ...]",
|
||||||
Action: expandVerkle,
|
Action: expandVerkle,
|
||||||
Flags: slices.Concat(utils.NetworkFlags, utils.DatabaseFlags),
|
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||||
Description: `
|
Description: `
|
||||||
geth verkle dump <state-root> <key 1> [<key 2> ...]
|
geth verkle dump <state-root> <key 1> [<key 2> ...]
|
||||||
This command will produce a dot file representing the tree, rooted at <root>.
|
This command will produce a dot file representing the tree, rooted at <root>.
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ func TestKeyID(t *testing.T) {
|
|||||||
{"third key", args{id: extractKeyId(gethPubKeys[2])}, "FD9813B2D2098484"},
|
{"third key", args{id: extractKeyId(gethPubKeys[2])}, "FD9813B2D2098484"},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if got := keyID(tt.args.id); got != tt.want {
|
if got := keyID(tt.args.id); got != tt.want {
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ func dump(in *inStream, s *rlp.Stream, depth int, out io.Writer) error {
|
|||||||
s.List()
|
s.List()
|
||||||
defer s.ListEnd()
|
defer s.ListEnd()
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
fmt.Fprint(out, ws(depth)+"[]")
|
fmt.Fprintf(out, ws(depth)+"[]")
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintln(out, ws(depth)+"[")
|
fmt.Fprintln(out, ws(depth)+"[")
|
||||||
for i := 0; ; i++ {
|
for i := 0; ; i++ {
|
||||||
|
|||||||
@@ -176,6 +176,12 @@ var (
|
|||||||
Usage: "Custom node name",
|
Usage: "Custom node name",
|
||||||
Category: flags.NetworkingCategory,
|
Category: flags.NetworkingCategory,
|
||||||
}
|
}
|
||||||
|
DocRootFlag = &flags.DirectoryFlag{
|
||||||
|
Name: "docroot",
|
||||||
|
Usage: "Document Root for HTTPClient file scheme",
|
||||||
|
Value: flags.DirectoryString(flags.HomeDir()),
|
||||||
|
Category: flags.APICategory,
|
||||||
|
}
|
||||||
ExitWhenSyncedFlag = &cli.BoolFlag{
|
ExitWhenSyncedFlag = &cli.BoolFlag{
|
||||||
Name: "exitwhensynced",
|
Name: "exitwhensynced",
|
||||||
Usage: "Exits after block synchronisation completes",
|
Usage: "Exits after block synchronisation completes",
|
||||||
@@ -211,7 +217,8 @@ var (
|
|||||||
Value: 0,
|
Value: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
SnapshotFlag = &cli.BoolFlag{
|
defaultSyncMode = ethconfig.Defaults.SyncMode
|
||||||
|
SnapshotFlag = &cli.BoolFlag{
|
||||||
Name: "snapshot",
|
Name: "snapshot",
|
||||||
Usage: `Enables snapshot-database mode (default = enable)`,
|
Usage: `Enables snapshot-database mode (default = enable)`,
|
||||||
Value: true,
|
Value: true,
|
||||||
@@ -243,10 +250,10 @@ var (
|
|||||||
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
|
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
SyncModeFlag = &cli.StringFlag{
|
SyncModeFlag = &flags.TextMarshalerFlag{
|
||||||
Name: "syncmode",
|
Name: "syncmode",
|
||||||
Usage: `Blockchain sync mode ("snap" or "full")`,
|
Usage: `Blockchain sync mode ("snap" or "full")`,
|
||||||
Value: ethconfig.Defaults.SyncMode.String(),
|
Value: &defaultSyncMode,
|
||||||
Category: flags.StateCategory,
|
Category: flags.StateCategory,
|
||||||
}
|
}
|
||||||
GCModeFlag = &cli.StringFlag{
|
GCModeFlag = &cli.StringFlag{
|
||||||
@@ -536,7 +543,6 @@ var (
|
|||||||
VMTraceJsonConfigFlag = &cli.StringFlag{
|
VMTraceJsonConfigFlag = &cli.StringFlag{
|
||||||
Name: "vmtrace.jsonconfig",
|
Name: "vmtrace.jsonconfig",
|
||||||
Usage: "Tracer configuration (JSON)",
|
Usage: "Tracer configuration (JSON)",
|
||||||
Value: "{}",
|
|
||||||
Category: flags.VMCategory,
|
Category: flags.VMCategory,
|
||||||
}
|
}
|
||||||
// API options.
|
// API options.
|
||||||
@@ -594,6 +600,11 @@ var (
|
|||||||
Usage: "Disables db compaction after import",
|
Usage: "Disables db compaction after import",
|
||||||
Category: flags.LoggingCategory,
|
Category: flags.LoggingCategory,
|
||||||
}
|
}
|
||||||
|
CollectWitnessFlag = &cli.BoolFlag{
|
||||||
|
Name: "collectwitness",
|
||||||
|
Usage: "Enable state witness generation during block execution. Work in progress flag, don't use.",
|
||||||
|
Category: flags.MiscCategory,
|
||||||
|
}
|
||||||
|
|
||||||
// MISC settings
|
// MISC settings
|
||||||
SyncTargetFlag = &cli.StringFlag{
|
SyncTargetFlag = &cli.StringFlag{
|
||||||
@@ -734,6 +745,11 @@ var (
|
|||||||
Value: node.DefaultConfig.BatchResponseMaxSize,
|
Value: node.DefaultConfig.BatchResponseMaxSize,
|
||||||
Category: flags.APICategory,
|
Category: flags.APICategory,
|
||||||
}
|
}
|
||||||
|
EnablePersonal = &cli.BoolFlag{
|
||||||
|
Name: "rpc.enabledeprecatedpersonal",
|
||||||
|
Usage: "Enables the (deprecated) personal namespace",
|
||||||
|
Category: flags.APICategory,
|
||||||
|
}
|
||||||
|
|
||||||
// Network Settings
|
// Network Settings
|
||||||
MaxPeersFlag = &cli.IntFlag{
|
MaxPeersFlag = &cli.IntFlag{
|
||||||
@@ -1296,6 +1312,7 @@ func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error
|
|||||||
func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
|
func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
if ctx.IsSet(MinerEtherbaseFlag.Name) {
|
if ctx.IsSet(MinerEtherbaseFlag.Name) {
|
||||||
log.Warn("Option --miner.etherbase is deprecated as the etherbase is set by the consensus client post-merge")
|
log.Warn("Option --miner.etherbase is deprecated as the etherbase is set by the consensus client post-merge")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if !ctx.IsSet(MinerPendingFeeRecipientFlag.Name) {
|
if !ctx.IsSet(MinerPendingFeeRecipientFlag.Name) {
|
||||||
return
|
return
|
||||||
@@ -1387,8 +1404,9 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
|
|||||||
if ctx.IsSet(JWTSecretFlag.Name) {
|
if ctx.IsSet(JWTSecretFlag.Name) {
|
||||||
cfg.JWTSecret = ctx.String(JWTSecretFlag.Name)
|
cfg.JWTSecret = ctx.String(JWTSecretFlag.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(EnablePersonal.Name) {
|
if ctx.IsSet(EnablePersonal.Name) {
|
||||||
log.Warn(fmt.Sprintf("Option --%s is deprecated. The 'personal' RPC namespace has been removed.", EnablePersonal.Name))
|
cfg.EnablePersonal = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet(ExternalSignerFlag.Name) {
|
if ctx.IsSet(ExternalSignerFlag.Name) {
|
||||||
@@ -1662,9 +1680,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||||||
if ctx.IsSet(SyncTargetFlag.Name) {
|
if ctx.IsSet(SyncTargetFlag.Name) {
|
||||||
cfg.SyncMode = downloader.FullSync // dev sync target forces full sync
|
cfg.SyncMode = downloader.FullSync // dev sync target forces full sync
|
||||||
} else if ctx.IsSet(SyncModeFlag.Name) {
|
} else if ctx.IsSet(SyncModeFlag.Name) {
|
||||||
if err = cfg.SyncMode.UnmarshalText([]byte(ctx.String(SyncModeFlag.Name))); err != nil {
|
cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
|
||||||
Fatalf("invalid --syncmode flag: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ctx.IsSet(NetworkIdFlag.Name) {
|
if ctx.IsSet(NetworkIdFlag.Name) {
|
||||||
cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name)
|
cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name)
|
||||||
@@ -1744,10 +1760,16 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||||||
cfg.SnapshotCache = 0 // Disabled
|
cfg.SnapshotCache = 0 // Disabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ctx.IsSet(DocRootFlag.Name) {
|
||||||
|
cfg.DocRoot = ctx.String(DocRootFlag.Name)
|
||||||
|
}
|
||||||
if ctx.IsSet(VMEnableDebugFlag.Name) {
|
if ctx.IsSet(VMEnableDebugFlag.Name) {
|
||||||
// TODO(fjl): force-enable this in --dev mode
|
// TODO(fjl): force-enable this in --dev mode
|
||||||
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
||||||
}
|
}
|
||||||
|
if ctx.IsSet(CollectWitnessFlag.Name) {
|
||||||
|
cfg.EnableWitnessCollection = ctx.Bool(CollectWitnessFlag.Name)
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
|
if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
|
||||||
cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
|
cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
|
||||||
@@ -1853,6 +1875,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Could not read genesis from database: %v", err)
|
Fatalf("Could not read genesis from database: %v", err)
|
||||||
}
|
}
|
||||||
|
if !genesis.Config.TerminalTotalDifficultyPassed {
|
||||||
|
Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficultyPassed must be true")
|
||||||
|
}
|
||||||
if genesis.Config.TerminalTotalDifficulty == nil {
|
if genesis.Config.TerminalTotalDifficulty == nil {
|
||||||
Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficulty must be specified")
|
Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficulty must be specified")
|
||||||
} else if genesis.Config.TerminalTotalDifficulty.Cmp(big.NewInt(0)) != 0 {
|
} else if genesis.Config.TerminalTotalDifficulty.Cmp(big.NewInt(0)) != 0 {
|
||||||
@@ -1883,8 +1908,13 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||||||
// VM tracing config.
|
// VM tracing config.
|
||||||
if ctx.IsSet(VMTraceFlag.Name) {
|
if ctx.IsSet(VMTraceFlag.Name) {
|
||||||
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
||||||
|
var config string
|
||||||
|
if ctx.IsSet(VMTraceJsonConfigFlag.Name) {
|
||||||
|
config = ctx.String(VMTraceJsonConfigFlag.Name)
|
||||||
|
}
|
||||||
|
|
||||||
cfg.VMTrace = name
|
cfg.VMTrace = name
|
||||||
cfg.VMTraceJsonConfig = ctx.String(VMTraceJsonConfigFlag.Name)
|
cfg.VMTraceJsonConfig = config
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1904,7 +1934,7 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
|
|||||||
|
|
||||||
// RegisterEthService adds an Ethereum client to the stack.
|
// RegisterEthService adds an Ethereum client to the stack.
|
||||||
// The second return value is the full node instance.
|
// The second return value is the full node instance.
|
||||||
func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (*eth.EthAPIBackend, *eth.Ethereum) {
|
func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) {
|
||||||
backend, err := eth.New(stack, cfg)
|
backend, err := eth.New(stack, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Failed to register the Ethereum service: %v", err)
|
Fatalf("Failed to register the Ethereum service: %v", err)
|
||||||
@@ -1914,7 +1944,7 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (*eth.EthAPIBac
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RegisterEthStatsService configures the Ethereum Stats daemon and adds it to the node.
|
// RegisterEthStatsService configures the Ethereum Stats daemon and adds it to the node.
|
||||||
func RegisterEthStatsService(stack *node.Node, backend *eth.EthAPIBackend, url string) {
|
func RegisterEthStatsService(stack *node.Node, backend ethapi.Backend, url string) {
|
||||||
if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil {
|
if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil {
|
||||||
Fatalf("Failed to register the Ethereum Stats service: %v", err)
|
Fatalf("Failed to register the Ethereum Stats service: %v", err)
|
||||||
}
|
}
|
||||||
@@ -2040,6 +2070,8 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
chainDb = remotedb.New(client)
|
chainDb = remotedb.New(client)
|
||||||
|
case ctx.String(SyncModeFlag.Name) == "light":
|
||||||
|
chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly)
|
||||||
default:
|
default:
|
||||||
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly)
|
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly)
|
||||||
}
|
}
|
||||||
@@ -2162,10 +2194,14 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
|||||||
}
|
}
|
||||||
vmcfg := vm.Config{
|
vmcfg := vm.Config{
|
||||||
EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name),
|
EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name),
|
||||||
|
EnableWitnessCollection: ctx.Bool(CollectWitnessFlag.Name),
|
||||||
}
|
}
|
||||||
if ctx.IsSet(VMTraceFlag.Name) {
|
if ctx.IsSet(VMTraceFlag.Name) {
|
||||||
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
if name := ctx.String(VMTraceFlag.Name); name != "" {
|
||||||
config := json.RawMessage(ctx.String(VMTraceJsonConfigFlag.Name))
|
var config json.RawMessage
|
||||||
|
if ctx.IsSet(VMTraceJsonConfigFlag.Name) {
|
||||||
|
config = json.RawMessage(ctx.String(VMTraceJsonConfigFlag.Name))
|
||||||
|
}
|
||||||
t, err := tracers.LiveDirectory.New(name, config)
|
t, err := tracers.LiveDirectory.New(name, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatalf("Failed to create tracer %q: %v", name, err)
|
Fatalf("Failed to create tracer %q: %v", name, err)
|
||||||
|
|||||||
@@ -153,12 +153,6 @@ var (
|
|||||||
Usage: "Enable expensive metrics collection and reporting (deprecated)",
|
Usage: "Enable expensive metrics collection and reporting (deprecated)",
|
||||||
Category: flags.DeprecatedCategory,
|
Category: flags.DeprecatedCategory,
|
||||||
}
|
}
|
||||||
// Deprecated Oct 2024
|
|
||||||
EnablePersonal = &cli.BoolFlag{
|
|
||||||
Name: "rpc.enabledeprecatedpersonal",
|
|
||||||
Usage: "This used to enable the 'personal' namespace.",
|
|
||||||
Category: flags.DeprecatedCategory,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ func Test_SplitTagsFlag(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if got := SplitTagsFlag(tt.args); !reflect.DeepEqual(got, tt.want) {
|
if got := SplitTagsFlag(tt.args); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ func TestGetPassPhraseWithList(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if got := GetPassPhraseWithList(tt.args.text, tt.args.confirmation, tt.args.index, tt.args.passwords); got != tt.want {
|
if got := GetPassPhraseWithList(tt.args.text, tt.args.confirmation, tt.args.index, tt.args.passwords); got != tt.want {
|
||||||
|
|||||||
@@ -24,9 +24,12 @@ import (
|
|||||||
|
|
||||||
// Various big integer limit values.
|
// Various big integer limit values.
|
||||||
var (
|
var (
|
||||||
|
tt255 = BigPow(2, 255)
|
||||||
tt256 = BigPow(2, 256)
|
tt256 = BigPow(2, 256)
|
||||||
tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1))
|
tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1))
|
||||||
|
tt63 = BigPow(2, 63)
|
||||||
MaxBig256 = new(big.Int).Set(tt256m1)
|
MaxBig256 = new(big.Int).Set(tt256m1)
|
||||||
|
MaxBig63 = new(big.Int).Sub(tt63, big.NewInt(1))
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -143,6 +146,32 @@ func BigPow(a, b int64) *big.Int {
|
|||||||
return r.Exp(r, big.NewInt(b), nil)
|
return r.Exp(r, big.NewInt(b), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BigMax returns the larger of x or y.
|
||||||
|
func BigMax(x, y *big.Int) *big.Int {
|
||||||
|
if x.Cmp(y) < 0 {
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// BigMin returns the smaller of x or y.
|
||||||
|
func BigMin(x, y *big.Int) *big.Int {
|
||||||
|
if x.Cmp(y) > 0 {
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// FirstBitSet returns the index of the first 1 bit in v, counting from LSB.
|
||||||
|
func FirstBitSet(v *big.Int) int {
|
||||||
|
for i := 0; i < v.BitLen(); i++ {
|
||||||
|
if v.Bit(i) > 0 {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v.BitLen()
|
||||||
|
}
|
||||||
|
|
||||||
// PaddedBigBytes encodes a big integer as a big-endian byte slice. The length
|
// PaddedBigBytes encodes a big integer as a big-endian byte slice. The length
|
||||||
// of the slice is at least n bytes.
|
// of the slice is at least n bytes.
|
||||||
func PaddedBigBytes(bigint *big.Int, n int) []byte {
|
func PaddedBigBytes(bigint *big.Int, n int) []byte {
|
||||||
@@ -154,6 +183,34 @@ func PaddedBigBytes(bigint *big.Int, n int) []byte {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bigEndianByteAt returns the byte at position n,
|
||||||
|
// in Big-Endian encoding
|
||||||
|
// So n==0 returns the least significant byte
|
||||||
|
func bigEndianByteAt(bigint *big.Int, n int) byte {
|
||||||
|
words := bigint.Bits()
|
||||||
|
// Check word-bucket the byte will reside in
|
||||||
|
i := n / wordBytes
|
||||||
|
if i >= len(words) {
|
||||||
|
return byte(0)
|
||||||
|
}
|
||||||
|
word := words[i]
|
||||||
|
// Offset of the byte
|
||||||
|
shift := 8 * uint(n%wordBytes)
|
||||||
|
|
||||||
|
return byte(word >> shift)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Byte returns the byte at position n,
|
||||||
|
// with the supplied padlength in Little-Endian encoding.
|
||||||
|
// n==0 returns the MSB
|
||||||
|
// Example: bigint '5', padlength 32, n=31 => 5
|
||||||
|
func Byte(bigint *big.Int, padlength, n int) byte {
|
||||||
|
if n >= padlength {
|
||||||
|
return byte(0)
|
||||||
|
}
|
||||||
|
return bigEndianByteAt(bigint, padlength-1-n)
|
||||||
|
}
|
||||||
|
|
||||||
// ReadBits encodes the absolute value of bigint as big-endian bytes. Callers must ensure
|
// ReadBits encodes the absolute value of bigint as big-endian bytes. Callers must ensure
|
||||||
// that buf has enough space. If buf is too short the result will be incomplete.
|
// that buf has enough space. If buf is too short the result will be incomplete.
|
||||||
func ReadBits(bigint *big.Int, buf []byte) {
|
func ReadBits(bigint *big.Int, buf []byte) {
|
||||||
@@ -177,3 +234,38 @@ func U256(x *big.Int) *big.Int {
|
|||||||
func U256Bytes(n *big.Int) []byte {
|
func U256Bytes(n *big.Int) []byte {
|
||||||
return PaddedBigBytes(U256(n), 32)
|
return PaddedBigBytes(U256(n), 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// S256 interprets x as a two's complement number.
|
||||||
|
// x must not exceed 256 bits (the result is undefined if it does) and is not modified.
|
||||||
|
//
|
||||||
|
// S256(0) = 0
|
||||||
|
// S256(1) = 1
|
||||||
|
// S256(2**255) = -2**255
|
||||||
|
// S256(2**256-1) = -1
|
||||||
|
func S256(x *big.Int) *big.Int {
|
||||||
|
if x.Cmp(tt255) < 0 {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
return new(big.Int).Sub(x, tt256)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exp implements exponentiation by squaring.
|
||||||
|
// Exp returns a newly-allocated big integer and does not change
|
||||||
|
// base or exponent. The result is truncated to 256 bits.
|
||||||
|
//
|
||||||
|
// Courtesy @karalabe and @chfast
|
||||||
|
func Exp(base, exponent *big.Int) *big.Int {
|
||||||
|
copyBase := new(big.Int).Set(base)
|
||||||
|
result := big.NewInt(1)
|
||||||
|
|
||||||
|
for _, word := range exponent.Bits() {
|
||||||
|
for i := 0; i < wordBits; i++ {
|
||||||
|
if word&1 == 1 {
|
||||||
|
U256(result.Mul(result, copyBase))
|
||||||
|
}
|
||||||
|
U256(copyBase.Mul(copyBase, copyBase))
|
||||||
|
word >>= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHexOrDecimal256(t *testing.T) {
|
func TestHexOrDecimal256(t *testing.T) {
|
||||||
@@ -68,6 +70,53 @@ func TestMustParseBig256(t *testing.T) {
|
|||||||
MustParseBig256("ggg")
|
MustParseBig256("ggg")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBigMax(t *testing.T) {
|
||||||
|
a := big.NewInt(10)
|
||||||
|
b := big.NewInt(5)
|
||||||
|
|
||||||
|
max1 := BigMax(a, b)
|
||||||
|
if max1 != a {
|
||||||
|
t.Errorf("Expected %d got %d", a, max1)
|
||||||
|
}
|
||||||
|
|
||||||
|
max2 := BigMax(b, a)
|
||||||
|
if max2 != a {
|
||||||
|
t.Errorf("Expected %d got %d", a, max2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBigMin(t *testing.T) {
|
||||||
|
a := big.NewInt(10)
|
||||||
|
b := big.NewInt(5)
|
||||||
|
|
||||||
|
min1 := BigMin(a, b)
|
||||||
|
if min1 != b {
|
||||||
|
t.Errorf("Expected %d got %d", b, min1)
|
||||||
|
}
|
||||||
|
|
||||||
|
min2 := BigMin(b, a)
|
||||||
|
if min2 != b {
|
||||||
|
t.Errorf("Expected %d got %d", b, min2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFirstBigSet(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
num *big.Int
|
||||||
|
ix int
|
||||||
|
}{
|
||||||
|
{big.NewInt(0), 0},
|
||||||
|
{big.NewInt(1), 0},
|
||||||
|
{big.NewInt(2), 1},
|
||||||
|
{big.NewInt(0x100), 8},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
if ix := FirstBitSet(test.num); ix != test.ix {
|
||||||
|
t.Errorf("FirstBitSet(b%b) = %d, want %d", test.num, ix, test.ix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPaddedBigBytes(t *testing.T) {
|
func TestPaddedBigBytes(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
num *big.Int
|
num *big.Int
|
||||||
@@ -107,6 +156,20 @@ func BenchmarkPaddedBigBytesSmallOnePadding(b *testing.B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkByteAtBrandNew(b *testing.B) {
|
||||||
|
bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
bigEndianByteAt(bigint, 15)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkByteAt(b *testing.B) {
|
||||||
|
bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
bigEndianByteAt(bigint, 15)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkByteAtOld(b *testing.B) {
|
func BenchmarkByteAtOld(b *testing.B) {
|
||||||
bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
|
bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
@@ -157,3 +220,105 @@ func TestU256Bytes(t *testing.T) {
|
|||||||
t.Errorf("expected %x got %x", ubytes, unsigned)
|
t.Errorf("expected %x got %x", ubytes, unsigned)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBigEndianByteAt(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
x string
|
||||||
|
y int
|
||||||
|
exp byte
|
||||||
|
}{
|
||||||
|
{"00", 0, 0x00},
|
||||||
|
{"01", 1, 0x00},
|
||||||
|
{"00", 1, 0x00},
|
||||||
|
{"01", 0, 0x01},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x30},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x20},
|
||||||
|
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0xAB},
|
||||||
|
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00},
|
||||||
|
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 500, 0x00},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
v := new(big.Int).SetBytes(common.Hex2Bytes(test.x))
|
||||||
|
actual := bigEndianByteAt(v, test.y)
|
||||||
|
if actual != test.exp {
|
||||||
|
t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func TestLittleEndianByteAt(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
x string
|
||||||
|
y int
|
||||||
|
exp byte
|
||||||
|
}{
|
||||||
|
{"00", 0, 0x00},
|
||||||
|
{"01", 1, 0x00},
|
||||||
|
{"00", 1, 0x00},
|
||||||
|
{"01", 0, 0x00},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000102030", 0, 0x00},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000102030", 1, 0x00},
|
||||||
|
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 31, 0x00},
|
||||||
|
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 32, 0x00},
|
||||||
|
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 0, 0xAB},
|
||||||
|
{"ABCDEF0908070605040302010000000000000000000000000000000000000000", 1, 0xCD},
|
||||||
|
{"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 0, 0x00},
|
||||||
|
{"00CDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff", 1, 0xCD},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000102030", 31, 0x30},
|
||||||
|
{"0000000000000000000000000000000000000000000000000000000000102030", 30, 0x20},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 32, 0x0},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 31, 0xFF},
|
||||||
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 0xFFFF, 0x0},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
v := new(big.Int).SetBytes(common.Hex2Bytes(test.x))
|
||||||
|
actual := Byte(v, 32, test.y)
|
||||||
|
if actual != test.exp {
|
||||||
|
t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestS256(t *testing.T) {
|
||||||
|
tests := []struct{ x, y *big.Int }{
|
||||||
|
{x: big.NewInt(0), y: big.NewInt(0)},
|
||||||
|
{x: big.NewInt(1), y: big.NewInt(1)},
|
||||||
|
{x: big.NewInt(2), y: big.NewInt(2)},
|
||||||
|
{
|
||||||
|
x: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)),
|
||||||
|
y: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: BigPow(2, 255),
|
||||||
|
y: new(big.Int).Neg(BigPow(2, 255)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1)),
|
||||||
|
y: big.NewInt(-1),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2)),
|
||||||
|
y: big.NewInt(-2),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
if y := S256(test.x); y.Cmp(test.y) != 0 {
|
||||||
|
t.Errorf("S256(%x) = %x, want %x", test.x, y, test.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExp(t *testing.T) {
|
||||||
|
tests := []struct{ base, exponent, result *big.Int }{
|
||||||
|
{base: big.NewInt(0), exponent: big.NewInt(0), result: big.NewInt(1)},
|
||||||
|
{base: big.NewInt(1), exponent: big.NewInt(0), result: big.NewInt(1)},
|
||||||
|
{base: big.NewInt(1), exponent: big.NewInt(1), result: big.NewInt(1)},
|
||||||
|
{base: big.NewInt(1), exponent: big.NewInt(2), result: big.NewInt(1)},
|
||||||
|
{base: big.NewInt(3), exponent: big.NewInt(144), result: MustParseBig256("507528786056415600719754159741696356908742250191663887263627442114881")},
|
||||||
|
{base: big.NewInt(2), exponent: big.NewInt(255), result: MustParseBig256("57896044618658097711785492504343953926634992332820282019728792003956564819968")},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
if result := Exp(test.base, test.exponent); result.Cmp(test.result) != 0 {
|
||||||
|
t.Errorf("Exp(%d, %d) = %d, want %d", test.base, test.exponent, result, test.result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,6 +22,22 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Integer limit values.
|
||||||
|
const (
|
||||||
|
MaxInt8 = 1<<7 - 1
|
||||||
|
MinInt8 = -1 << 7
|
||||||
|
MaxInt16 = 1<<15 - 1
|
||||||
|
MinInt16 = -1 << 15
|
||||||
|
MaxInt32 = 1<<31 - 1
|
||||||
|
MinInt32 = -1 << 31
|
||||||
|
MaxInt64 = 1<<63 - 1
|
||||||
|
MinInt64 = -1 << 63
|
||||||
|
MaxUint8 = 1<<8 - 1
|
||||||
|
MaxUint16 = 1<<16 - 1
|
||||||
|
MaxUint32 = 1<<32 - 1
|
||||||
|
MaxUint64 = 1<<64 - 1
|
||||||
|
)
|
||||||
|
|
||||||
// HexOrDecimal64 marshals uint64 as hex or decimal.
|
// HexOrDecimal64 marshals uint64 as hex or decimal.
|
||||||
type HexOrDecimal64 uint64
|
type HexOrDecimal64 uint64
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package math
|
package math
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,8 +36,8 @@ func TestOverflow(t *testing.T) {
|
|||||||
op operation
|
op operation
|
||||||
}{
|
}{
|
||||||
// add operations
|
// add operations
|
||||||
{math.MaxUint64, 1, true, add},
|
{MaxUint64, 1, true, add},
|
||||||
{math.MaxUint64 - 1, 1, false, add},
|
{MaxUint64 - 1, 1, false, add},
|
||||||
|
|
||||||
// sub operations
|
// sub operations
|
||||||
{0, 1, true, sub},
|
{0, 1, true, sub},
|
||||||
@@ -47,8 +46,8 @@ func TestOverflow(t *testing.T) {
|
|||||||
// mul operations
|
// mul operations
|
||||||
{0, 0, false, mul},
|
{0, 0, false, mul},
|
||||||
{10, 10, false, mul},
|
{10, 10, false, mul},
|
||||||
{math.MaxUint64, 2, true, mul},
|
{MaxUint64, 2, true, mul},
|
||||||
{math.MaxUint64, 1, false, mul},
|
{MaxUint64, 1, false, mul},
|
||||||
} {
|
} {
|
||||||
var overflows bool
|
var overflows bool
|
||||||
switch test.op {
|
switch test.op {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ func FileExist(filePath string) bool {
|
|||||||
if err != nil && os.IsNotExist(err) {
|
if err != nil && os.IsNotExist(err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
@@ -116,6 +115,9 @@ func errOut(n int, err error) chan error {
|
|||||||
func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) ([]*types.Header, []*types.Header, error) {
|
func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) ([]*types.Header, []*types.Header, error) {
|
||||||
// TTD is not defined yet, all headers should be in legacy format.
|
// TTD is not defined yet, all headers should be in legacy format.
|
||||||
ttd := chain.Config().TerminalTotalDifficulty
|
ttd := chain.Config().TerminalTotalDifficulty
|
||||||
|
if ttd == nil {
|
||||||
|
return headers, nil, nil
|
||||||
|
}
|
||||||
ptd := chain.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1)
|
ptd := chain.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1)
|
||||||
if ptd == nil {
|
if ptd == nil {
|
||||||
return nil, nil, consensus.ErrUnknownAncestor
|
return nil, nil, consensus.ErrUnknownAncestor
|
||||||
@@ -347,7 +349,7 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finalize implements consensus.Engine and processes withdrawals on top.
|
// Finalize implements consensus.Engine and processes withdrawals on top.
|
||||||
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
|
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) {
|
||||||
if !beacon.IsPoSHeader(header) {
|
if !beacon.IsPoSHeader(header) {
|
||||||
beacon.ethone.Finalize(chain, header, state, body)
|
beacon.ethone.Finalize(chain, header, state, body)
|
||||||
return
|
return
|
||||||
@@ -492,6 +494,9 @@ func (beacon *Beacon) SetThreads(threads int) {
|
|||||||
// It depends on the parentHash already being stored in the database.
|
// It depends on the parentHash already being stored in the database.
|
||||||
// If the parentHash is not stored in the database a UnknownAncestor error is returned.
|
// If the parentHash is not stored in the database a UnknownAncestor error is returned.
|
||||||
func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, parentNumber uint64) (bool, error) {
|
func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, parentNumber uint64) (bool, error) {
|
||||||
|
if chain.Config().TerminalTotalDifficulty == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
td := chain.GetTd(parentHash, parentNumber)
|
td := chain.GetTd(parentHash, parentNumber)
|
||||||
if td == nil {
|
if td == nil {
|
||||||
return false, consensus.ErrUnknownAncestor
|
return false, consensus.ErrUnknownAncestor
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/common/lru"
|
"github.com/ethereum/go-ethereum/common/lru"
|
||||||
@@ -35,7 +36,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
@@ -50,6 +50,8 @@ const (
|
|||||||
checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database
|
checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database
|
||||||
inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory
|
inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory
|
||||||
inmemorySignatures = 4096 // Number of recent block signatures to keep in memory
|
inmemorySignatures = 4096 // Number of recent block signatures to keep in memory
|
||||||
|
|
||||||
|
wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers
|
||||||
)
|
)
|
||||||
|
|
||||||
// Clique proof-of-authority protocol constants.
|
// Clique proof-of-authority protocol constants.
|
||||||
@@ -138,6 +140,9 @@ var (
|
|||||||
errRecentlySigned = errors.New("recently signed")
|
errRecentlySigned = errors.New("recently signed")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SignerFn hashes and signs the data to be signed by a backing account.
|
||||||
|
type SignerFn func(signer accounts.Account, mimeType string, message []byte) ([]byte, error)
|
||||||
|
|
||||||
// ecrecover extracts the Ethereum account address from a signed header.
|
// ecrecover extracts the Ethereum account address from a signed header.
|
||||||
func ecrecover(header *types.Header, sigcache *sigLRU) (common.Address, error) {
|
func ecrecover(header *types.Header, sigcache *sigLRU) (common.Address, error) {
|
||||||
// If the signature's already cached, return that
|
// If the signature's already cached, return that
|
||||||
@@ -175,6 +180,7 @@ type Clique struct {
|
|||||||
proposals map[common.Address]bool // Current list of proposals we are pushing
|
proposals map[common.Address]bool // Current list of proposals we are pushing
|
||||||
|
|
||||||
signer common.Address // Ethereum address of the signing key
|
signer common.Address // Ethereum address of the signing key
|
||||||
|
signFn SignerFn // Signer function to authorize hashes with
|
||||||
lock sync.RWMutex // Protects the signer and proposals fields
|
lock sync.RWMutex // Protects the signer and proposals fields
|
||||||
|
|
||||||
// The fields below are for testing only
|
// The fields below are for testing only
|
||||||
@@ -574,7 +580,7 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
|
|||||||
|
|
||||||
// Finalize implements consensus.Engine. There is no post-transaction
|
// Finalize implements consensus.Engine. There is no post-transaction
|
||||||
// consensus rules in clique, do nothing here.
|
// consensus rules in clique, do nothing here.
|
||||||
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
|
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) {
|
||||||
// No block rewards in PoA, so the state remains as is
|
// No block rewards in PoA, so the state remains as is
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,17 +602,82 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
|
|||||||
|
|
||||||
// Authorize injects a private key into the consensus engine to mint new blocks
|
// Authorize injects a private key into the consensus engine to mint new blocks
|
||||||
// with.
|
// with.
|
||||||
func (c *Clique) Authorize(signer common.Address) {
|
func (c *Clique) Authorize(signer common.Address, signFn SignerFn) {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
c.signer = signer
|
c.signer = signer
|
||||||
|
c.signFn = signFn
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seal implements consensus.Engine, attempting to create a sealed block using
|
// Seal implements consensus.Engine, attempting to create a sealed block using
|
||||||
// the local signing credentials.
|
// the local signing credentials.
|
||||||
func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
|
func (c *Clique) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
|
||||||
panic("clique (poa) sealing not supported any more")
|
header := block.Header()
|
||||||
|
|
||||||
|
// Sealing the genesis block is not supported
|
||||||
|
number := header.Number.Uint64()
|
||||||
|
if number == 0 {
|
||||||
|
return errUnknownBlock
|
||||||
|
}
|
||||||
|
// For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing)
|
||||||
|
if c.config.Period == 0 && len(block.Transactions()) == 0 {
|
||||||
|
return errors.New("sealing paused while waiting for transactions")
|
||||||
|
}
|
||||||
|
// Don't hold the signer fields for the entire sealing procedure
|
||||||
|
c.lock.RLock()
|
||||||
|
signer, signFn := c.signer, c.signFn
|
||||||
|
c.lock.RUnlock()
|
||||||
|
|
||||||
|
// Bail out if we're unauthorized to sign a block
|
||||||
|
snap, err := c.snapshot(chain, number-1, header.ParentHash, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, authorized := snap.Signers[signer]; !authorized {
|
||||||
|
return errUnauthorizedSigner
|
||||||
|
}
|
||||||
|
// If we're amongst the recent signers, wait for the next block
|
||||||
|
for seen, recent := range snap.Recents {
|
||||||
|
if recent == signer {
|
||||||
|
// Signer is among recents, only wait if the current block doesn't shift it out
|
||||||
|
if limit := uint64(len(snap.Signers)/2 + 1); number < limit || seen > number-limit {
|
||||||
|
return errors.New("signed recently, must wait for others")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sweet, the protocol permits us to sign the block, wait for our time
|
||||||
|
delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple
|
||||||
|
if header.Difficulty.Cmp(diffNoTurn) == 0 {
|
||||||
|
// It's not our turn explicitly to sign, delay it a bit
|
||||||
|
wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime
|
||||||
|
delay += time.Duration(rand.Int63n(int64(wiggle)))
|
||||||
|
|
||||||
|
log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle))
|
||||||
|
}
|
||||||
|
// Sign all the things!
|
||||||
|
sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeClique, CliqueRLP(header))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
copy(header.Extra[len(header.Extra)-extraSeal:], sighash)
|
||||||
|
// Wait until sealing is terminated or delay timeout.
|
||||||
|
log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
|
||||||
|
go func() {
|
||||||
|
select {
|
||||||
|
case <-stop:
|
||||||
|
return
|
||||||
|
case <-time.After(delay):
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case results <- block.WithSeal(header):
|
||||||
|
default:
|
||||||
|
log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import (
|
|||||||
"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/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
@@ -89,7 +88,7 @@ type Engine interface {
|
|||||||
//
|
//
|
||||||
// Note: The state database might be updated to reflect any consensus rules
|
// Note: The state database might be updated to reflect any consensus rules
|
||||||
// that happen at finalization (e.g. block rewards).
|
// that happen at finalization (e.g. block rewards).
|
||||||
Finalize(chain ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body)
|
Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body)
|
||||||
|
|
||||||
// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
|
// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
|
||||||
// rewards or process withdrawals) and assembles the final block.
|
// rewards or process withdrawals) and assembles the final block.
|
||||||
|
|||||||
@@ -24,13 +24,13 @@ import (
|
|||||||
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
@@ -480,9 +480,7 @@ func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int {
|
|||||||
expDiff := periodCount.Sub(periodCount, big2)
|
expDiff := periodCount.Sub(periodCount, big2)
|
||||||
expDiff.Exp(big2, expDiff, nil)
|
expDiff.Exp(big2, expDiff, nil)
|
||||||
diff.Add(diff, expDiff)
|
diff.Add(diff, expDiff)
|
||||||
if diff.Cmp(params.MinimumDifficulty) < 0 {
|
diff = math.BigMax(diff, params.MinimumDifficulty)
|
||||||
diff = params.MinimumDifficulty
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return diff
|
return diff
|
||||||
}
|
}
|
||||||
@@ -504,7 +502,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finalize implements consensus.Engine, accumulating the block and uncle rewards.
|
// Finalize implements consensus.Engine, accumulating the block and uncle rewards.
|
||||||
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
|
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) {
|
||||||
// Accumulate any block and uncle rewards
|
// Accumulate any block and uncle rewards
|
||||||
accumulateRewards(chain.Config(), state, header, body.Uncles)
|
accumulateRewards(chain.Config(), state, header, body.Uncles)
|
||||||
}
|
}
|
||||||
@@ -567,7 +565,7 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
|
|||||||
// accumulateRewards credits the coinbase of the given block with the mining
|
// accumulateRewards credits the coinbase of the given block with the mining
|
||||||
// reward. The total reward consists of the static block reward and rewards for
|
// reward. The total reward consists of the static block reward and rewards for
|
||||||
// included uncles. The coinbase of each uncle block is also rewarded.
|
// included uncles. The coinbase of each uncle block is also rewarded.
|
||||||
func accumulateRewards(config *params.ChainConfig, stateDB vm.StateDB, header *types.Header, uncles []*types.Header) {
|
func accumulateRewards(config *params.ChainConfig, stateDB *state.StateDB, header *types.Header, uncles []*types.Header) {
|
||||||
// Select the correct block reward based on chain progression
|
// Select the correct block reward based on chain progression
|
||||||
blockReward := FrontierBlockReward
|
blockReward := FrontierBlockReward
|
||||||
if config.IsByzantium(header.Number) {
|
if config.IsByzantium(header.Number) {
|
||||||
|
|||||||
@@ -21,10 +21,11 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -73,7 +74,7 @@ func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header)
|
|||||||
// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
|
// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
|
||||||
// rules, transferring all balances of a set of DAO accounts to a single refund
|
// rules, transferring all balances of a set of DAO accounts to a single refund
|
||||||
// contract.
|
// contract.
|
||||||
func ApplyDAOHardFork(statedb vm.StateDB) {
|
func ApplyDAOHardFork(statedb *state.StateDB) {
|
||||||
// Retrieve the contract to refund balances into
|
// Retrieve the contract to refund balances into
|
||||||
if !statedb.Exist(params.DAORefundContract) {
|
if !statedb.Exist(params.DAORefundContract) {
|
||||||
statedb.CreateAccount(params.DAORefundContract)
|
statedb.CreateAccount(params.DAORefundContract)
|
||||||
@@ -81,8 +82,7 @@ func ApplyDAOHardFork(statedb vm.StateDB) {
|
|||||||
|
|
||||||
// Move every DAO account and extra-balance account funds into the refund contract
|
// Move every DAO account and extra-balance account funds into the refund contract
|
||||||
for _, addr := range params.DAODrainList() {
|
for _, addr := range params.DAODrainList() {
|
||||||
balance := statedb.GetBalance(addr)
|
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr), tracing.BalanceIncreaseDaoContract)
|
||||||
statedb.AddBalance(params.DAORefundContract, balance, tracing.BalanceIncreaseDaoContract)
|
statedb.SetBalance(addr, new(uint256.Int), tracing.BalanceDecreaseDaoAccount)
|
||||||
statedb.SubBalance(addr, balance, tracing.BalanceDecreaseDaoAccount)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
@@ -77,10 +78,9 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
|||||||
num.Mul(num, parent.BaseFee)
|
num.Mul(num, parent.BaseFee)
|
||||||
num.Div(num, denom.SetUint64(parentGasTarget))
|
num.Div(num, denom.SetUint64(parentGasTarget))
|
||||||
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
|
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
|
||||||
if num.Cmp(common.Big1) < 0 {
|
baseFeeDelta := math.BigMax(num, common.Big1)
|
||||||
return num.Add(parent.BaseFee, common.Big1)
|
|
||||||
}
|
return num.Add(parent.BaseFee, baseFeeDelta)
|
||||||
return num.Add(parent.BaseFee, num)
|
|
||||||
} else {
|
} else {
|
||||||
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
|
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
|
||||||
// max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
|
// max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
|
||||||
@@ -88,11 +88,8 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
|||||||
num.Mul(num, parent.BaseFee)
|
num.Mul(num, parent.BaseFee)
|
||||||
num.Div(num, denom.SetUint64(parentGasTarget))
|
num.Div(num, denom.SetUint64(parentGasTarget))
|
||||||
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
|
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
|
||||||
|
|
||||||
baseFee := num.Sub(parent.BaseFee, num)
|
baseFee := num.Sub(parent.BaseFee, num)
|
||||||
if baseFee.Cmp(common.Big0) < 0 {
|
|
||||||
baseFee = common.Big0
|
return math.BigMax(baseFee, common.Big0)
|
||||||
}
|
|
||||||
return baseFee
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,15 @@ package console
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dop251/goja"
|
"github.com/dop251/goja"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/scwallet"
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/usbwallet"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/console/prompt"
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/internal/jsre"
|
"github.com/ethereum/go-ethereum/internal/jsre"
|
||||||
@@ -48,6 +51,268 @@ func newBridge(client *rpc.Client, prompter prompt.UserPrompter, printer io.Writ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getJeth(vm *goja.Runtime) *goja.Object {
|
||||||
|
jeth := vm.Get("jeth")
|
||||||
|
if jeth == nil {
|
||||||
|
panic(vm.ToValue("jeth object does not exist"))
|
||||||
|
}
|
||||||
|
return jeth.ToObject(vm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAccount is a wrapper around the personal.newAccount RPC method that uses a
|
||||||
|
// non-echoing password prompt to acquire the passphrase and executes the original
|
||||||
|
// RPC method (saved in jeth.newAccount) with it to actually execute the RPC call.
|
||||||
|
func (b *bridge) NewAccount(call jsre.Call) (goja.Value, error) {
|
||||||
|
var (
|
||||||
|
password string
|
||||||
|
confirm string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
switch {
|
||||||
|
// No password was specified, prompt the user for it
|
||||||
|
case len(call.Arguments) == 0:
|
||||||
|
if password, err = b.prompter.PromptPassword("Passphrase: "); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if confirm, err = b.prompter.PromptPassword("Repeat passphrase: "); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if password != confirm {
|
||||||
|
return nil, errors.New("passwords don't match")
|
||||||
|
}
|
||||||
|
// A single string password was specified, use that
|
||||||
|
case len(call.Arguments) == 1 && call.Argument(0).ToString() != nil:
|
||||||
|
password = call.Argument(0).ToString().String()
|
||||||
|
default:
|
||||||
|
return nil, errors.New("expected 0 or 1 string argument")
|
||||||
|
}
|
||||||
|
// Password acquired, execute the call and return
|
||||||
|
newAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("newAccount"))
|
||||||
|
if !callable {
|
||||||
|
return nil, errors.New("jeth.newAccount is not callable")
|
||||||
|
}
|
||||||
|
ret, err := newAccount(goja.Null(), call.VM.ToValue(password))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenWallet is a wrapper around personal.openWallet which can interpret and
|
||||||
|
// react to certain error messages, such as the Trezor PIN matrix request.
|
||||||
|
func (b *bridge) OpenWallet(call jsre.Call) (goja.Value, error) {
|
||||||
|
// Make sure we have a wallet specified to open
|
||||||
|
if call.Argument(0).ToObject(call.VM).ClassName() != "String" {
|
||||||
|
return nil, errors.New("first argument must be the wallet URL to open")
|
||||||
|
}
|
||||||
|
wallet := call.Argument(0)
|
||||||
|
|
||||||
|
var passwd goja.Value
|
||||||
|
if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) {
|
||||||
|
passwd = call.VM.ToValue("")
|
||||||
|
} else {
|
||||||
|
passwd = call.Argument(1)
|
||||||
|
}
|
||||||
|
// Open the wallet and return if successful in itself
|
||||||
|
openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet"))
|
||||||
|
if !callable {
|
||||||
|
return nil, errors.New("jeth.openWallet is not callable")
|
||||||
|
}
|
||||||
|
val, err := openWallet(goja.Null(), wallet, passwd)
|
||||||
|
if err == nil {
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wallet open failed, report error unless it's a PIN or PUK entry
|
||||||
|
switch {
|
||||||
|
case strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()):
|
||||||
|
val, err = b.readPinAndReopenWallet(call)
|
||||||
|
if err == nil {
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
val, err = b.readPassphraseAndReopenWallet(call)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
case strings.HasSuffix(err.Error(), scwallet.ErrPairingPasswordNeeded.Error()):
|
||||||
|
// PUK input requested, fetch from the user and call open again
|
||||||
|
input, err := b.prompter.PromptPassword("Please enter the pairing password: ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
passwd = call.VM.ToValue(input)
|
||||||
|
if val, err = openWallet(goja.Null(), wallet, passwd); err != nil {
|
||||||
|
if !strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// PIN input requested, fetch from the user and call open again
|
||||||
|
input, err := b.prompter.PromptPassword("Please enter current PIN: ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case strings.HasSuffix(err.Error(), scwallet.ErrPINUnblockNeeded.Error()):
|
||||||
|
// PIN unblock requested, fetch PUK and new PIN from the user
|
||||||
|
var pukpin string
|
||||||
|
input, err := b.prompter.PromptPassword("Please enter current PUK: ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pukpin = input
|
||||||
|
input, err = b.prompter.PromptPassword("Please enter new PIN: ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pukpin += input
|
||||||
|
|
||||||
|
if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(pukpin)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
case strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()):
|
||||||
|
// PIN input requested, fetch from the user and call open again
|
||||||
|
input, err := b.prompter.PromptPassword("Please enter current PIN: ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Unknown error occurred, drop to the user
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bridge) readPassphraseAndReopenWallet(call jsre.Call) (goja.Value, error) {
|
||||||
|
wallet := call.Argument(0)
|
||||||
|
input, err := b.prompter.PromptPassword("Please enter your passphrase: ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet"))
|
||||||
|
if !callable {
|
||||||
|
return nil, errors.New("jeth.openWallet is not callable")
|
||||||
|
}
|
||||||
|
return openWallet(goja.Null(), wallet, call.VM.ToValue(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bridge) readPinAndReopenWallet(call jsre.Call) (goja.Value, error) {
|
||||||
|
wallet := call.Argument(0)
|
||||||
|
// Trezor PIN matrix input requested, display the matrix to the user and fetch the data
|
||||||
|
fmt.Fprintf(b.printer, "Look at the device for number positions\n\n")
|
||||||
|
fmt.Fprintf(b.printer, "7 | 8 | 9\n")
|
||||||
|
fmt.Fprintf(b.printer, "--+---+--\n")
|
||||||
|
fmt.Fprintf(b.printer, "4 | 5 | 6\n")
|
||||||
|
fmt.Fprintf(b.printer, "--+---+--\n")
|
||||||
|
fmt.Fprintf(b.printer, "1 | 2 | 3\n\n")
|
||||||
|
|
||||||
|
input, err := b.prompter.PromptPassword("Please enter current PIN: ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet"))
|
||||||
|
if !callable {
|
||||||
|
return nil, errors.New("jeth.openWallet is not callable")
|
||||||
|
}
|
||||||
|
return openWallet(goja.Null(), wallet, call.VM.ToValue(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnlockAccount is a wrapper around the personal.unlockAccount RPC method that
|
||||||
|
// uses a non-echoing password prompt to acquire the passphrase and executes the
|
||||||
|
// original RPC method (saved in jeth.unlockAccount) with it to actually execute
|
||||||
|
// the RPC call.
|
||||||
|
func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) {
|
||||||
|
if len(call.Arguments) < 1 {
|
||||||
|
return nil, errors.New("usage: unlockAccount(account, [ password, duration ])")
|
||||||
|
}
|
||||||
|
|
||||||
|
account := call.Argument(0)
|
||||||
|
// Make sure we have an account specified to unlock.
|
||||||
|
if goja.IsUndefined(account) || goja.IsNull(account) || account.ExportType().Kind() != reflect.String {
|
||||||
|
return nil, errors.New("first argument must be the account to unlock")
|
||||||
|
}
|
||||||
|
|
||||||
|
// If password is not given or is the null value, prompt the user for it.
|
||||||
|
var passwd goja.Value
|
||||||
|
if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) {
|
||||||
|
fmt.Fprintf(b.printer, "Unlock account %s\n", account)
|
||||||
|
input, err := b.prompter.PromptPassword("Passphrase: ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
passwd = call.VM.ToValue(input)
|
||||||
|
} else {
|
||||||
|
if call.Argument(1).ExportType().Kind() != reflect.String {
|
||||||
|
return nil, errors.New("password must be a string")
|
||||||
|
}
|
||||||
|
passwd = call.Argument(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third argument is the duration how long the account should be unlocked.
|
||||||
|
duration := goja.Null()
|
||||||
|
if !goja.IsUndefined(call.Argument(2)) && !goja.IsNull(call.Argument(2)) {
|
||||||
|
if !isNumber(call.Argument(2)) {
|
||||||
|
return nil, errors.New("unlock duration must be a number")
|
||||||
|
}
|
||||||
|
duration = call.Argument(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the request to the backend and return.
|
||||||
|
unlockAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("unlockAccount"))
|
||||||
|
if !callable {
|
||||||
|
return nil, errors.New("jeth.unlockAccount is not callable")
|
||||||
|
}
|
||||||
|
return unlockAccount(goja.Null(), account, passwd, duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign is a wrapper around the personal.sign RPC method that uses a non-echoing password
|
||||||
|
// prompt to acquire the passphrase and executes the original RPC method (saved in
|
||||||
|
// jeth.sign) with it to actually execute the RPC call.
|
||||||
|
func (b *bridge) Sign(call jsre.Call) (goja.Value, error) {
|
||||||
|
if nArgs := len(call.Arguments); nArgs < 2 {
|
||||||
|
return nil, errors.New("usage: sign(message, account, [ password ])")
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
message = call.Argument(0)
|
||||||
|
account = call.Argument(1)
|
||||||
|
passwd = call.Argument(2)
|
||||||
|
)
|
||||||
|
|
||||||
|
if goja.IsUndefined(message) || message.ExportType().Kind() != reflect.String {
|
||||||
|
return nil, errors.New("first argument must be the message to sign")
|
||||||
|
}
|
||||||
|
if goja.IsUndefined(account) || account.ExportType().Kind() != reflect.String {
|
||||||
|
return nil, errors.New("second argument must be the account to sign with")
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the password is not given or null ask the user and ensure password is a string
|
||||||
|
if goja.IsUndefined(passwd) || goja.IsNull(passwd) {
|
||||||
|
fmt.Fprintf(b.printer, "Give password for account %s\n", account)
|
||||||
|
input, err := b.prompter.PromptPassword("Password: ")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
passwd = call.VM.ToValue(input)
|
||||||
|
} else if passwd.ExportType().Kind() != reflect.String {
|
||||||
|
return nil, errors.New("third argument must be the password to unlock the account")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the request to the backend and return
|
||||||
|
sign, callable := goja.AssertFunction(getJeth(call.VM).Get("sign"))
|
||||||
|
if !callable {
|
||||||
|
return nil, errors.New("jeth.sign is not callable")
|
||||||
|
}
|
||||||
|
return sign(goja.Null(), message, account, passwd)
|
||||||
|
}
|
||||||
|
|
||||||
// Sleep will block the console for the specified number of seconds.
|
// Sleep will block the console for the specified number of seconds.
|
||||||
func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) {
|
func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) {
|
||||||
if nArgs := len(call.Arguments); nArgs < 1 {
|
if nArgs := len(call.Arguments); nArgs < 1 {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 The go-ethereum Authors
|
// Copyright 2020 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of the go-ethereum library.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
@@ -14,11 +14,35 @@
|
|||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package version
|
package console
|
||||||
|
|
||||||
const (
|
import (
|
||||||
Major = 1 // Major version component of the current release
|
"testing"
|
||||||
Minor = 14 // Minor version component of the current release
|
|
||||||
Patch = 12 // Patch version component of the current release
|
"github.com/dop251/goja"
|
||||||
Meta = "unstable" // Version metadata to append to the version string
|
"github.com/ethereum/go-ethereum/internal/jsre"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TestUndefinedAsParam ensures that personal functions can receive
|
||||||
|
// `undefined` as a parameter.
|
||||||
|
func TestUndefinedAsParam(t *testing.T) {
|
||||||
|
b := bridge{}
|
||||||
|
call := jsre.Call{}
|
||||||
|
call.Arguments = []goja.Value{goja.Undefined()}
|
||||||
|
|
||||||
|
b.UnlockAccount(call)
|
||||||
|
b.Sign(call)
|
||||||
|
b.Sleep(call)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestNullAsParam ensures that personal functions can receive
|
||||||
|
// `null` as a parameter.
|
||||||
|
func TestNullAsParam(t *testing.T) {
|
||||||
|
b := bridge{}
|
||||||
|
call := jsre.Call{}
|
||||||
|
call.Arguments = []goja.Value{goja.Null()}
|
||||||
|
|
||||||
|
b.UnlockAccount(call)
|
||||||
|
b.Sign(call)
|
||||||
|
b.Sleep(call)
|
||||||
|
}
|
||||||
@@ -142,6 +142,7 @@ func (c *Console) init(preload []string) error {
|
|||||||
// Add bridge overrides for web3.js functionality.
|
// Add bridge overrides for web3.js functionality.
|
||||||
c.jsre.Do(func(vm *goja.Runtime) {
|
c.jsre.Do(func(vm *goja.Runtime) {
|
||||||
c.initAdmin(vm, bridge)
|
c.initAdmin(vm, bridge)
|
||||||
|
c.initPersonal(vm, bridge)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Preload JavaScript files.
|
// Preload JavaScript files.
|
||||||
@@ -248,6 +249,30 @@ func (c *Console) initAdmin(vm *goja.Runtime, bridge *bridge) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initPersonal redirects account-related API methods through the bridge.
|
||||||
|
//
|
||||||
|
// If the console is in interactive mode and the 'personal' API is available, override
|
||||||
|
// the openWallet, unlockAccount, newAccount and sign methods since these require user
|
||||||
|
// interaction. The original web3 callbacks are stored in 'jeth'. These will be called
|
||||||
|
// by the bridge after the prompt and send the original web3 request to the backend.
|
||||||
|
func (c *Console) initPersonal(vm *goja.Runtime, bridge *bridge) {
|
||||||
|
personal := getObject(vm, "personal")
|
||||||
|
if personal == nil || c.prompter == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Warn("Enabling deprecated personal namespace")
|
||||||
|
jeth := vm.NewObject()
|
||||||
|
vm.Set("jeth", jeth)
|
||||||
|
jeth.Set("openWallet", personal.Get("openWallet"))
|
||||||
|
jeth.Set("unlockAccount", personal.Get("unlockAccount"))
|
||||||
|
jeth.Set("newAccount", personal.Get("newAccount"))
|
||||||
|
jeth.Set("sign", personal.Get("sign"))
|
||||||
|
personal.Set("openWallet", jsre.MakeCallback(vm, bridge.OpenWallet))
|
||||||
|
personal.Set("unlockAccount", jsre.MakeCallback(vm, bridge.UnlockAccount))
|
||||||
|
personal.Set("newAccount", jsre.MakeCallback(vm, bridge.NewAccount))
|
||||||
|
personal.Set("sign", jsre.MakeCallback(vm, bridge.Sign))
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Console) clearHistory() {
|
func (c *Console) clearHistory() {
|
||||||
c.history = nil
|
c.history = nil
|
||||||
c.prompter.ClearHistory()
|
c.prompter.ClearHistory()
|
||||||
|
|||||||
@@ -26,13 +26,12 @@ import (
|
|||||||
|
|
||||||
// Iterator for disassembled EVM instructions
|
// Iterator for disassembled EVM instructions
|
||||||
type instructionIterator struct {
|
type instructionIterator struct {
|
||||||
code []byte
|
code []byte
|
||||||
pc uint64
|
pc uint64
|
||||||
arg []byte
|
arg []byte
|
||||||
op vm.OpCode
|
op vm.OpCode
|
||||||
error error
|
error error
|
||||||
started bool
|
started bool
|
||||||
eofEnabled bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInstructionIterator creates a new instruction iterator.
|
// NewInstructionIterator creates a new instruction iterator.
|
||||||
@@ -42,13 +41,6 @@ func NewInstructionIterator(code []byte) *instructionIterator {
|
|||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEOFInstructionIterator creates a new instruction iterator for EOF-code.
|
|
||||||
func NewEOFInstructionIterator(code []byte) *instructionIterator {
|
|
||||||
it := NewInstructionIterator(code)
|
|
||||||
it.eofEnabled = true
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next returns true if there is a next instruction and moves on.
|
// Next returns true if there is a next instruction and moves on.
|
||||||
func (it *instructionIterator) Next() bool {
|
func (it *instructionIterator) Next() bool {
|
||||||
if it.error != nil || uint64(len(it.code)) <= it.pc {
|
if it.error != nil || uint64(len(it.code)) <= it.pc {
|
||||||
@@ -71,26 +63,13 @@ func (it *instructionIterator) Next() bool {
|
|||||||
// We reached the end.
|
// We reached the end.
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
it.op = vm.OpCode(it.code[it.pc])
|
it.op = vm.OpCode(it.code[it.pc])
|
||||||
var a int
|
if it.op.IsPush() {
|
||||||
if !it.eofEnabled { // Legacy code
|
a := uint64(it.op) - uint64(vm.PUSH0)
|
||||||
if it.op.IsPush() {
|
u := it.pc + 1 + a
|
||||||
a = int(it.op) - int(vm.PUSH0)
|
|
||||||
}
|
|
||||||
} else { // EOF code
|
|
||||||
if it.op == vm.RJUMPV {
|
|
||||||
// RJUMPV is unique as it has a variable sized operand. The total size is
|
|
||||||
// determined by the count byte which immediately follows RJUMPV.
|
|
||||||
maxIndex := int(it.code[it.pc+1])
|
|
||||||
a = (maxIndex+1)*2 + 1
|
|
||||||
} else {
|
|
||||||
a = vm.Immediates(it.op)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if a > 0 {
|
|
||||||
u := it.pc + 1 + uint64(a)
|
|
||||||
if uint64(len(it.code)) <= it.pc || uint64(len(it.code)) < u {
|
if uint64(len(it.code)) <= it.pc || uint64(len(it.code)) < u {
|
||||||
it.error = fmt.Errorf("incomplete instruction at %v", it.pc)
|
it.error = fmt.Errorf("incomplete push instruction at %v", it.pc)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
it.arg = it.code[it.pc+1 : u]
|
it.arg = it.code[it.pc+1 : u]
|
||||||
@@ -126,6 +105,7 @@ func PrintDisassembled(code string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
it := NewInstructionIterator(script)
|
it := NewInstructionIterator(script)
|
||||||
for it.Next() {
|
for it.Next() {
|
||||||
if it.Arg() != nil && 0 < len(it.Arg()) {
|
if it.Arg() != nil && 0 < len(it.Arg()) {
|
||||||
|
|||||||
@@ -17,78 +17,42 @@
|
|||||||
package asm
|
package asm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"encoding/hex"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tests disassembling instructions
|
// Tests disassembling instructions
|
||||||
func TestInstructionIterator(t *testing.T) {
|
func TestInstructionIterator(t *testing.T) {
|
||||||
for i, tc := range []struct {
|
for i, tc := range []struct {
|
||||||
code string
|
want int
|
||||||
legacyWant string
|
code string
|
||||||
eofWant string
|
wantErr string
|
||||||
}{
|
}{
|
||||||
{"", "", ""}, // empty
|
{2, "61000000", ""}, // valid code
|
||||||
{"6100", `err: incomplete instruction at 0`, `err: incomplete instruction at 0`},
|
{0, "6100", "incomplete push instruction at 0"}, // invalid code
|
||||||
{"61000000", `
|
{2, "5900", ""}, // push0
|
||||||
00000: PUSH2 0x0000
|
{0, "", ""}, // empty
|
||||||
00003: STOP`, `
|
|
||||||
00000: PUSH2 0x0000
|
|
||||||
00003: STOP`},
|
|
||||||
{"5F00", `
|
|
||||||
00000: PUSH0
|
|
||||||
00001: STOP`, `
|
|
||||||
00000: PUSH0
|
|
||||||
00001: STOP`},
|
|
||||||
{"d1aabb00", `00000: DATALOADN
|
|
||||||
00001: opcode 0xaa not defined
|
|
||||||
00002: opcode 0xbb not defined
|
|
||||||
00003: STOP`, `
|
|
||||||
00000: DATALOADN 0xaabb
|
|
||||||
00003: STOP`}, // DATALOADN(aabb),STOP
|
|
||||||
{"d1aa", `
|
|
||||||
00000: DATALOADN
|
|
||||||
00001: opcode 0xaa not defined`, "err: incomplete instruction at 0\n"}, // DATALOADN(aa) invalid
|
|
||||||
{"e20211223344556600", `
|
|
||||||
00000: RJUMPV
|
|
||||||
00001: MUL
|
|
||||||
00002: GT
|
|
||||||
00003: opcode 0x22 not defined
|
|
||||||
00004: CALLER
|
|
||||||
00005: DIFFICULTY
|
|
||||||
00006: SSTORE
|
|
||||||
err: incomplete instruction at 7`, `
|
|
||||||
00000: RJUMPV 0x02112233445566
|
|
||||||
00008: STOP`}, // RJUMPV( 6 bytes), STOP
|
|
||||||
|
|
||||||
} {
|
} {
|
||||||
var (
|
var (
|
||||||
|
have int
|
||||||
code, _ = hex.DecodeString(tc.code)
|
code, _ = hex.DecodeString(tc.code)
|
||||||
legacy = strings.TrimSpace(disassembly(NewInstructionIterator(code)))
|
it = NewInstructionIterator(code)
|
||||||
eof = strings.TrimSpace(disassembly(NewEOFInstructionIterator(code)))
|
|
||||||
)
|
)
|
||||||
if want := strings.TrimSpace(tc.legacyWant); legacy != want {
|
for it.Next() {
|
||||||
t.Errorf("test %d: wrong (legacy) output. have:\n%q\nwant:\n%q\n", i, legacy, want)
|
have++
|
||||||
}
|
}
|
||||||
if want := strings.TrimSpace(tc.eofWant); eof != want {
|
var haveErr = ""
|
||||||
t.Errorf("test %d: wrong (eof) output. have:\n%q\nwant:\n%q\n", i, eof, want)
|
if it.Error() != nil {
|
||||||
|
haveErr = it.Error().Error()
|
||||||
|
}
|
||||||
|
if haveErr != tc.wantErr {
|
||||||
|
t.Errorf("test %d: encountered error: %q want %q", i, haveErr, tc.wantErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if have != tc.want {
|
||||||
|
t.Errorf("wrong instruction count, have %d want %d", have, tc.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func disassembly(it *instructionIterator) string {
|
|
||||||
var out = new(strings.Builder)
|
|
||||||
for it.Next() {
|
|
||||||
if it.Arg() != nil && 0 < len(it.Arg()) {
|
|
||||||
fmt.Fprintf(out, "%05x: %v %#x\n", it.PC(), it.Op(), it.Arg())
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(out, "%05x: %v\n", it.PC(), it.Op())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := it.Error(); err != nil {
|
|
||||||
fmt.Fprintf(out, "err: %v\n", err)
|
|
||||||
}
|
|
||||||
return out.String()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -174,16 +173,18 @@ func genUncles(i int, gen *BlockGen) {
|
|||||||
func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||||
// Create the database in memory or in a temporary directory.
|
// Create the database in memory or in a temporary directory.
|
||||||
var db ethdb.Database
|
var db ethdb.Database
|
||||||
|
var err error
|
||||||
if !disk {
|
if !disk {
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
} else {
|
} else {
|
||||||
pdb, err := pebble.New(b.TempDir(), 128, 128, "", false)
|
dir := b.TempDir()
|
||||||
|
db, err = rawdb.NewLevelDBDatabase(dir, 128, 128, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("cannot create temporary database: %v", err)
|
b.Fatalf("cannot create temporary database: %v", err)
|
||||||
}
|
}
|
||||||
db = rawdb.NewDatabase(pdb)
|
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a chain of b.N blocks using the supplied block
|
// Generate a chain of b.N blocks using the supplied block
|
||||||
// generator function.
|
// generator function.
|
||||||
gspec := &Genesis{
|
gspec := &Genesis{
|
||||||
@@ -280,11 +281,11 @@ func makeChainForBench(db ethdb.Database, genesis *Genesis, full bool, count uin
|
|||||||
func benchWriteChain(b *testing.B, full bool, count uint64) {
|
func benchWriteChain(b *testing.B, full bool, count uint64) {
|
||||||
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
pdb, err := pebble.New(b.TempDir(), 1024, 128, "", false)
|
dir := b.TempDir()
|
||||||
|
db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database: %v", err)
|
b.Fatalf("error opening database at %v: %v", dir, err)
|
||||||
}
|
}
|
||||||
db := rawdb.NewDatabase(pdb)
|
|
||||||
makeChainForBench(db, genesis, full, count)
|
makeChainForBench(db, genesis, full, count)
|
||||||
db.Close()
|
db.Close()
|
||||||
}
|
}
|
||||||
@@ -293,12 +294,10 @@ func benchWriteChain(b *testing.B, full bool, count uint64) {
|
|||||||
func benchReadChain(b *testing.B, full bool, count uint64) {
|
func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||||
dir := b.TempDir()
|
dir := b.TempDir()
|
||||||
|
|
||||||
pdb, err := pebble.New(dir, 1024, 128, "", false)
|
db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database: %v", err)
|
b.Fatalf("error opening database at %v: %v", dir, err)
|
||||||
}
|
}
|
||||||
db := rawdb.NewDatabase(pdb)
|
|
||||||
|
|
||||||
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
genesis := &Genesis{Config: params.AllEthashProtocolChanges}
|
||||||
makeChainForBench(db, genesis, full, count)
|
makeChainForBench(db, genesis, full, count)
|
||||||
db.Close()
|
db.Close()
|
||||||
@@ -309,16 +308,15 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
|||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
pdb, err = pebble.New(dir, 1024, 128, "", false)
|
db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error opening database: %v", err)
|
b.Fatalf("error opening database at %v: %v", dir, err)
|
||||||
}
|
}
|
||||||
db = rawdb.NewDatabase(pdb)
|
|
||||||
|
|
||||||
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
|
chain, err := NewBlockChain(db, &cacheConfig, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("error creating chain: %v", err)
|
b.Fatalf("error creating chain: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for n := uint64(0); n < count; n++ {
|
for n := uint64(0); n < count; n++ {
|
||||||
header := chain.GetHeaderByNumber(n)
|
header := chain.GetHeaderByNumber(n)
|
||||||
if full {
|
if full {
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"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/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
@@ -121,7 +123,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
|||||||
// such as amount of used gas, the receipt roots and the state root itself.
|
// such as amount of used gas, the receipt roots and the state root itself.
|
||||||
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, res *ProcessResult, stateless bool) error {
|
func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, res *ProcessResult, stateless bool) error {
|
||||||
if res == nil {
|
if res == nil {
|
||||||
return errors.New("nil ProcessResult value")
|
return fmt.Errorf("nil ProcessResult value")
|
||||||
}
|
}
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
if block.GasUsed() != res.GasUsed {
|
if block.GasUsed() != res.GasUsed {
|
||||||
@@ -145,12 +147,10 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
|||||||
}
|
}
|
||||||
// Validate the parsed requests match the expected header value.
|
// Validate the parsed requests match the expected header value.
|
||||||
if header.RequestsHash != nil {
|
if header.RequestsHash != nil {
|
||||||
reqhash := types.CalcRequestsHash(res.Requests)
|
depositSha := types.DeriveSha(res.Requests, trie.NewStackTrie(nil))
|
||||||
if reqhash != *header.RequestsHash {
|
if depositSha != *header.RequestsHash {
|
||||||
return fmt.Errorf("invalid requests hash (remote: %x local: %x)", *header.RequestsHash, reqhash)
|
return fmt.Errorf("invalid deposit root hash (remote: %x local: %x)", *header.RequestsHash, depositSha)
|
||||||
}
|
}
|
||||||
} else if res.Requests != nil {
|
|
||||||
return errors.New("block has requests before prague fork")
|
|
||||||
}
|
}
|
||||||
// Validate the state root against the received state root and throw
|
// Validate the state root against the received state root and throw
|
||||||
// an error if they don't match.
|
// an error if they don't match.
|
||||||
@@ -160,6 +160,28 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateWitness cross validates a block execution with stateless remote clients.
|
||||||
|
//
|
||||||
|
// Normally we'd distribute the block witness to remote cross validators, wait
|
||||||
|
// for them to respond and then merge the results. For now, however, it's only
|
||||||
|
// Geth, so do an internal stateless run.
|
||||||
|
func (v *BlockValidator) ValidateWitness(witness *stateless.Witness, receiptRoot common.Hash, stateRoot common.Hash) error {
|
||||||
|
// Run the cross client stateless execution
|
||||||
|
// TODO(karalabe): Self-stateless for now, swap with other clients
|
||||||
|
crossReceiptRoot, crossStateRoot, err := ExecuteStateless(v.config, witness)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("stateless execution failed: %v", err)
|
||||||
|
}
|
||||||
|
// Stateless cross execution suceeeded, validate the withheld computed fields
|
||||||
|
if crossReceiptRoot != receiptRoot {
|
||||||
|
return fmt.Errorf("cross validator receipt root mismatch (cross: %x local: %x)", crossReceiptRoot, receiptRoot)
|
||||||
|
}
|
||||||
|
if crossStateRoot != stateRoot {
|
||||||
|
return fmt.Errorf("cross validator state root mismatch (cross: %x local: %x)", crossStateRoot, stateRoot)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// CalcGasLimit computes the gas limit of the next block after parent. It aims
|
// CalcGasLimit computes the gas limit of the next block after parent. It aims
|
||||||
// to keep the baseline gas close to the provided target, and increase it towards
|
// to keep the baseline gas close to the provided target, and increase it towards
|
||||||
// the target if the baseline gas is lower.
|
// the target if the baseline gas is lower.
|
||||||
|
|||||||
@@ -113,12 +113,8 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
|||||||
}
|
}
|
||||||
copy(gspec.ExtraData[32:], addr[:])
|
copy(gspec.ExtraData[32:], addr[:])
|
||||||
|
|
||||||
// chain_maker has no blockchain to retrieve the TTD from, setting to nil
|
|
||||||
// is a hack to signal it to generate pre-merge blocks
|
|
||||||
gspec.Config.TerminalTotalDifficulty = nil
|
|
||||||
td := 0
|
td := 0
|
||||||
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil)
|
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil)
|
||||||
|
|
||||||
for i, block := range blocks {
|
for i, block := range blocks {
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
@@ -149,6 +145,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
|||||||
}
|
}
|
||||||
preBlocks = blocks
|
preBlocks = blocks
|
||||||
gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td))
|
gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td))
|
||||||
|
t.Logf("Set ttd to %v\n", gspec.Config.TerminalTotalDifficulty)
|
||||||
postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, func(i int, gen *BlockGen) {
|
postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
})
|
})
|
||||||
@@ -204,7 +201,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
|||||||
t.Fatalf("post-block %d: unexpected result returned: %v", i, result)
|
t.Fatalf("post-block %d: unexpected result returned: %v", i, result)
|
||||||
case <-time.After(25 * time.Millisecond):
|
case <-time.After(25 * time.Millisecond):
|
||||||
}
|
}
|
||||||
chain.InsertBlockWithoutSetHead(postBlocks[i], false)
|
chain.InsertBlockWithoutSetHead(postBlocks[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the blocks with pre-merge blocks and post-merge blocks
|
// Verify the blocks with pre-merge blocks and post-merge blocks
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"runtime"
|
"runtime"
|
||||||
"slices"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -79,11 +78,10 @@ var (
|
|||||||
snapshotCommitTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/commits", nil)
|
snapshotCommitTimer = metrics.NewRegisteredResettingTimer("chain/snapshot/commits", nil)
|
||||||
triedbCommitTimer = metrics.NewRegisteredResettingTimer("chain/triedb/commits", nil)
|
triedbCommitTimer = metrics.NewRegisteredResettingTimer("chain/triedb/commits", nil)
|
||||||
|
|
||||||
blockInsertTimer = metrics.NewRegisteredResettingTimer("chain/inserts", nil)
|
blockInsertTimer = metrics.NewRegisteredResettingTimer("chain/inserts", nil)
|
||||||
blockValidationTimer = metrics.NewRegisteredResettingTimer("chain/validation", nil)
|
blockValidationTimer = metrics.NewRegisteredResettingTimer("chain/validation", nil)
|
||||||
blockCrossValidationTimer = metrics.NewRegisteredResettingTimer("chain/crossvalidation", nil)
|
blockExecutionTimer = metrics.NewRegisteredResettingTimer("chain/execution", nil)
|
||||||
blockExecutionTimer = metrics.NewRegisteredResettingTimer("chain/execution", nil)
|
blockWriteTimer = metrics.NewRegisteredResettingTimer("chain/write", nil)
|
||||||
blockWriteTimer = metrics.NewRegisteredResettingTimer("chain/write", nil)
|
|
||||||
|
|
||||||
blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil)
|
blockReorgMeter = metrics.NewRegisteredMeter("chain/reorg/executes", nil)
|
||||||
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
|
blockReorgAddMeter = metrics.NewRegisteredMeter("chain/reorg/add", nil)
|
||||||
@@ -160,9 +158,9 @@ func (c *CacheConfig) triedbConfig(isVerkle bool) *triedb.Config {
|
|||||||
}
|
}
|
||||||
if c.StateScheme == rawdb.PathScheme {
|
if c.StateScheme == rawdb.PathScheme {
|
||||||
config.PathDB = &pathdb.Config{
|
config.PathDB = &pathdb.Config{
|
||||||
StateHistory: c.StateHistory,
|
StateHistory: c.StateHistory,
|
||||||
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
CleanCacheSize: c.TrieCleanLimit * 1024 * 1024,
|
||||||
WriteBufferSize: c.TrieDirtyLimit * 1024 * 1024,
|
DirtyCacheSize: c.TrieDirtyLimit * 1024 * 1024,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
@@ -225,6 +223,7 @@ type BlockChain struct {
|
|||||||
hc *HeaderChain
|
hc *HeaderChain
|
||||||
rmLogsFeed event.Feed
|
rmLogsFeed event.Feed
|
||||||
chainFeed event.Feed
|
chainFeed event.Feed
|
||||||
|
chainSideFeed event.Feed
|
||||||
chainHeadFeed event.Feed
|
chainHeadFeed event.Feed
|
||||||
logsFeed event.Feed
|
logsFeed event.Feed
|
||||||
blockProcFeed event.Feed
|
blockProcFeed event.Feed
|
||||||
@@ -571,14 +570,15 @@ func (bc *BlockChain) SetHead(head uint64) error {
|
|||||||
}
|
}
|
||||||
// Send chain head event to update the transaction pool
|
// Send chain head event to update the transaction pool
|
||||||
header := bc.CurrentBlock()
|
header := bc.CurrentBlock()
|
||||||
if block := bc.GetBlock(header.Hash(), header.Number.Uint64()); block == nil {
|
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
|
||||||
|
if block == nil {
|
||||||
// This should never happen. In practice, previously currentBlock
|
// This should never happen. In practice, previously currentBlock
|
||||||
// contained the entire block whereas now only a "marker", so there
|
// contained the entire block whereas now only a "marker", so there
|
||||||
// is an ever so slight chance for a race we should handle.
|
// is an ever so slight chance for a race we should handle.
|
||||||
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
|
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
|
||||||
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
|
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
|
||||||
}
|
}
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Header: header})
|
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -592,14 +592,15 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error {
|
|||||||
}
|
}
|
||||||
// Send chain head event to update the transaction pool
|
// Send chain head event to update the transaction pool
|
||||||
header := bc.CurrentBlock()
|
header := bc.CurrentBlock()
|
||||||
if block := bc.GetBlock(header.Hash(), header.Number.Uint64()); block == nil {
|
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
|
||||||
|
if block == nil {
|
||||||
// This should never happen. In practice, previously currentBlock
|
// This should never happen. In practice, previously currentBlock
|
||||||
// contained the entire block whereas now only a "marker", so there
|
// contained the entire block whereas now only a "marker", so there
|
||||||
// is an ever so slight chance for a race we should handle.
|
// is an ever so slight chance for a race we should handle.
|
||||||
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
|
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
|
||||||
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
|
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
|
||||||
}
|
}
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Header: header})
|
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1436,7 +1437,7 @@ func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (e
|
|||||||
func (bc *BlockChain) writeKnownBlock(block *types.Block) error {
|
func (bc *BlockChain) writeKnownBlock(block *types.Block) error {
|
||||||
current := bc.CurrentBlock()
|
current := bc.CurrentBlock()
|
||||||
if block.ParentHash() != current.Hash() {
|
if block.ParentHash() != current.Hash() {
|
||||||
if err := bc.reorg(current, block.Header()); err != nil {
|
if err := bc.reorg(current, block); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1542,7 +1543,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
|||||||
|
|
||||||
// Reorganise the chain if the parent is not the head block
|
// Reorganise the chain if the parent is not the head block
|
||||||
if block.ParentHash() != currentBlock.Hash() {
|
if block.ParentHash() != currentBlock.Hash() {
|
||||||
if err := bc.reorg(currentBlock, block.Header()); err != nil {
|
if err := bc.reorg(currentBlock, block); err != nil {
|
||||||
return NonStatTy, err
|
return NonStatTy, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1550,7 +1551,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
|||||||
// Set new head.
|
// Set new head.
|
||||||
bc.writeHeadBlock(block)
|
bc.writeHeadBlock(block)
|
||||||
|
|
||||||
bc.chainFeed.Send(ChainEvent{Header: block.Header()})
|
bc.chainFeed.Send(ChainEvent{Block: block, Hash: block.Hash(), Logs: logs})
|
||||||
if len(logs) > 0 {
|
if len(logs) > 0 {
|
||||||
bc.logsFeed.Send(logs)
|
bc.logsFeed.Send(logs)
|
||||||
}
|
}
|
||||||
@@ -1560,7 +1561,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
|
|||||||
// we will fire an accumulated ChainHeadEvent and disable fire
|
// we will fire an accumulated ChainHeadEvent and disable fire
|
||||||
// event here.
|
// event here.
|
||||||
if emitHeadEvent {
|
if emitHeadEvent {
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Header: block.Header()})
|
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
||||||
}
|
}
|
||||||
return CanonStatTy, nil
|
return CanonStatTy, nil
|
||||||
}
|
}
|
||||||
@@ -1597,9 +1598,7 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
|||||||
return 0, errChainStopped
|
return 0, errChainStopped
|
||||||
}
|
}
|
||||||
defer bc.chainmu.Unlock()
|
defer bc.chainmu.Unlock()
|
||||||
|
return bc.insertChain(chain, true)
|
||||||
_, n, err := bc.insertChain(chain, true, false) // No witness collection for mass inserts (would get super large)
|
|
||||||
return n, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// insertChain is the internal implementation of InsertChain, which assumes that
|
// insertChain is the internal implementation of InsertChain, which assumes that
|
||||||
@@ -1610,10 +1609,10 @@ func (bc *BlockChain) InsertChain(chain types.Blocks) (int, error) {
|
|||||||
// racey behaviour. If a sidechain import is in progress, and the historic state
|
// racey behaviour. If a sidechain import is in progress, and the historic state
|
||||||
// is imported, but then new canon-head is added before the actual sidechain
|
// is imported, but then new canon-head is added before the actual sidechain
|
||||||
// completes, then the historic state could be pruned again
|
// completes, then the historic state could be pruned again
|
||||||
func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness bool) (*stateless.Witness, int, error) {
|
func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) {
|
||||||
// If the chain is terminating, don't even bother starting up.
|
// If the chain is terminating, don't even bother starting up.
|
||||||
if bc.insertStopped() {
|
if bc.insertStopped() {
|
||||||
return nil, 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
|
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
|
||||||
SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()), chain)
|
SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()), chain)
|
||||||
@@ -1625,7 +1624,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
// Fire a single chain head event if we've progressed the chain
|
// Fire a single chain head event if we've progressed the chain
|
||||||
defer func() {
|
defer func() {
|
||||||
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Header: lastCanon.Header()})
|
bc.chainHeadFeed.Send(ChainHeadEvent{lastCanon})
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
// Start the parallel header verifier
|
// Start the parallel header verifier
|
||||||
@@ -1668,7 +1667,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
for block != nil && bc.skipBlock(err, it) {
|
for block != nil && bc.skipBlock(err, it) {
|
||||||
log.Debug("Writing previously known block", "number", block.Number(), "hash", block.Hash())
|
log.Debug("Writing previously known block", "number", block.Number(), "hash", block.Hash())
|
||||||
if err := bc.writeKnownBlock(block); err != nil {
|
if err := bc.writeKnownBlock(block); err != nil {
|
||||||
return nil, it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
lastCanon = block
|
lastCanon = block
|
||||||
|
|
||||||
@@ -1682,12 +1681,12 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
if setHead {
|
if setHead {
|
||||||
// First block is pruned, insert as sidechain and reorg only if TD grows enough
|
// First block is pruned, insert as sidechain and reorg only if TD grows enough
|
||||||
log.Debug("Pruned ancestor, inserting as sidechain", "number", block.Number(), "hash", block.Hash())
|
log.Debug("Pruned ancestor, inserting as sidechain", "number", block.Number(), "hash", block.Hash())
|
||||||
return bc.insertSideChain(block, it, makeWitness)
|
return bc.insertSideChain(block, it)
|
||||||
} else {
|
} else {
|
||||||
// We're post-merge and the parent is pruned, try to recover the parent state
|
// We're post-merge and the parent is pruned, try to recover the parent state
|
||||||
log.Debug("Pruned ancestor", "number", block.Number(), "hash", block.Hash())
|
log.Debug("Pruned ancestor", "number", block.Number(), "hash", block.Hash())
|
||||||
_, err := bc.recoverAncestors(block, makeWitness)
|
_, err := bc.recoverAncestors(block)
|
||||||
return nil, it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
// Some other error(except ErrKnownBlock) occurred, abort.
|
// Some other error(except ErrKnownBlock) occurred, abort.
|
||||||
// ErrKnownBlock is allowed here since some known blocks
|
// ErrKnownBlock is allowed here since some known blocks
|
||||||
@@ -1695,7 +1694,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
case err != nil && !errors.Is(err, ErrKnownBlock):
|
case err != nil && !errors.Is(err, ErrKnownBlock):
|
||||||
stats.ignored += len(it.chain)
|
stats.ignored += len(it.chain)
|
||||||
bc.reportBlock(block, nil, err)
|
bc.reportBlock(block, nil, err)
|
||||||
return nil, it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
// No validation errors for the first block (or chain prefix skipped)
|
// No validation errors for the first block (or chain prefix skipped)
|
||||||
var activeState *state.StateDB
|
var activeState *state.StateDB
|
||||||
@@ -1709,9 +1708,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Track the singleton witness from this chain insertion (if any)
|
|
||||||
var witness *stateless.Witness
|
|
||||||
|
|
||||||
for ; block != nil && err == nil || errors.Is(err, ErrKnownBlock); block, err = it.next() {
|
for ; block != nil && err == nil || errors.Is(err, ErrKnownBlock); block, err = it.next() {
|
||||||
// If the chain is terminating, stop processing blocks
|
// If the chain is terminating, stop processing blocks
|
||||||
if bc.insertStopped() {
|
if bc.insertStopped() {
|
||||||
@@ -1748,7 +1744,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
"hash", block.Hash(), "number", block.NumberU64())
|
"hash", block.Hash(), "number", block.NumberU64())
|
||||||
}
|
}
|
||||||
if err := bc.writeKnownBlock(block); err != nil {
|
if err := bc.writeKnownBlock(block); err != nil {
|
||||||
return nil, it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
stats.processed++
|
stats.processed++
|
||||||
if bc.logger != nil && bc.logger.OnSkippedBlock != nil {
|
if bc.logger != nil && bc.logger.OnSkippedBlock != nil {
|
||||||
@@ -1759,11 +1755,13 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
Safe: bc.CurrentSafeBlock(),
|
Safe: bc.CurrentSafeBlock(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can assume that logs are empty here, since the only way for consecutive
|
// We can assume that logs are empty here, since the only way for consecutive
|
||||||
// Clique blocks to have the same state is if there are no transactions.
|
// Clique blocks to have the same state is if there are no transactions.
|
||||||
lastCanon = block
|
lastCanon = block
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the parent block and it's state to execute on top
|
// Retrieve the parent block and it's state to execute on top
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
parent := it.previous()
|
parent := it.previous()
|
||||||
@@ -1772,20 +1770,19 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
}
|
}
|
||||||
statedb, err := state.New(parent.Root, bc.statedb)
|
statedb, err := state.New(parent.Root, bc.statedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
|
statedb.SetLogger(bc.logger)
|
||||||
|
|
||||||
// If we are past Byzantium, enable prefetching to pull in trie node paths
|
// If we are past Byzantium, enable prefetching to pull in trie node paths
|
||||||
// while processing transactions. Before Byzantium the prefetcher is mostly
|
// while processing transactions. Before Byzantium the prefetcher is mostly
|
||||||
// useless due to the intermediate root hashing after each transaction.
|
// useless due to the intermediate root hashing after each transaction.
|
||||||
if bc.chainConfig.IsByzantium(block.Number()) {
|
if bc.chainConfig.IsByzantium(block.Number()) {
|
||||||
// Generate witnesses either if we're self-testing, or if it's the
|
var witness *stateless.Witness
|
||||||
// only block being inserted. A bit crude, but witnesses are huge,
|
if bc.vmConfig.EnableWitnessCollection {
|
||||||
// so we refuse to make an entire chain of them.
|
witness, err = stateless.NewWitness(bc, block)
|
||||||
if bc.vmConfig.StatelessSelfValidation || (makeWitness && len(chain) == 1) {
|
|
||||||
witness, err = stateless.NewWitness(block.Header(), bc)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statedb.StartPrefetcher("chain", witness)
|
statedb.StartPrefetcher("chain", witness)
|
||||||
@@ -1817,7 +1814,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
res, err := bc.processBlock(block, statedb, start, setHead)
|
res, err := bc.processBlock(block, statedb, start, setHead)
|
||||||
followupInterrupt.Store(true)
|
followupInterrupt.Store(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
// Report the import stats before returning the various results
|
// Report the import stats before returning the various results
|
||||||
stats.processed++
|
stats.processed++
|
||||||
@@ -1834,7 +1831,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
// After merge we expect few side chains. Simply count
|
// After merge we expect few side chains. Simply count
|
||||||
// all blocks the CL gives us for GC processing time
|
// all blocks the CL gives us for GC processing time
|
||||||
bc.gcproc += res.procTime
|
bc.gcproc += res.procTime
|
||||||
return witness, it.index, nil // Direct block insertion of a single block
|
return it.index, nil // Direct block insertion of a single block
|
||||||
}
|
}
|
||||||
switch res.status {
|
switch res.status {
|
||||||
case CanonStatTy:
|
case CanonStatTy:
|
||||||
@@ -1864,7 +1861,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
stats.ignored += it.remaining()
|
stats.ignored += it.remaining()
|
||||||
return witness, it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// blockProcessingResult is a summary of block processing
|
// blockProcessingResult is a summary of block processing
|
||||||
@@ -1909,36 +1906,13 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
|||||||
}
|
}
|
||||||
vtime := time.Since(vstart)
|
vtime := time.Since(vstart)
|
||||||
|
|
||||||
// If witnesses was generated and stateless self-validation requested, do
|
if witness := statedb.Witness(); witness != nil {
|
||||||
// that now. Self validation should *never* run in production, it's more of
|
if err = bc.validator.ValidateWitness(witness, block.ReceiptHash(), block.Root()); err != nil {
|
||||||
// a tight integration to enable running *all* consensus tests through the
|
bc.reportBlock(block, res, err)
|
||||||
// witness builder/runner, which would otherwise be impossible due to the
|
return nil, fmt.Errorf("cross verification failed: %v", err)
|
||||||
// various invalid chain states/behaviors being contained in those tests.
|
|
||||||
xvstart := time.Now()
|
|
||||||
if witness := statedb.Witness(); witness != nil && bc.vmConfig.StatelessSelfValidation {
|
|
||||||
log.Warn("Running stateless self-validation", "block", block.Number(), "hash", block.Hash())
|
|
||||||
|
|
||||||
// Remove critical computed fields from the block to force true recalculation
|
|
||||||
context := block.Header()
|
|
||||||
context.Root = common.Hash{}
|
|
||||||
context.ReceiptHash = common.Hash{}
|
|
||||||
|
|
||||||
task := types.NewBlockWithHeader(context).WithBody(*block.Body())
|
|
||||||
|
|
||||||
// Run the stateless self-cross-validation
|
|
||||||
crossStateRoot, crossReceiptRoot, err := ExecuteStateless(bc.chainConfig, task, witness)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("stateless self-validation failed: %v", err)
|
|
||||||
}
|
|
||||||
if crossStateRoot != block.Root() {
|
|
||||||
return nil, fmt.Errorf("stateless self-validation root mismatch (cross: %x local: %x)", crossStateRoot, block.Root())
|
|
||||||
}
|
|
||||||
if crossReceiptRoot != block.ReceiptHash() {
|
|
||||||
return nil, fmt.Errorf("stateless self-validation receipt root mismatch (cross: %x local: %x)", crossReceiptRoot, block.ReceiptHash())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xvtime := time.Since(xvstart)
|
proctime := time.Since(start) // processing + validation
|
||||||
proctime := time.Since(start) // processing + validation + cross validation
|
|
||||||
|
|
||||||
// Update the metrics touched during block processing and validation
|
// Update the metrics touched during block processing and validation
|
||||||
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
accountReadTimer.Update(statedb.AccountReads) // Account reads are complete(in processing)
|
||||||
@@ -1956,7 +1930,6 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
|||||||
trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on tries update
|
trieUpdate := statedb.AccountUpdates + statedb.StorageUpdates // The time spent on tries update
|
||||||
blockExecutionTimer.Update(ptime - (statedb.AccountReads + statedb.StorageReads)) // The time spent on EVM processing
|
blockExecutionTimer.Update(ptime - (statedb.AccountReads + statedb.StorageReads)) // The time spent on EVM processing
|
||||||
blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation
|
blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation
|
||||||
blockCrossValidationTimer.Update(xvtime) // The time spent on stateless cross validation
|
|
||||||
|
|
||||||
// Write the block to the chain and get the status.
|
// Write the block to the chain and get the status.
|
||||||
var (
|
var (
|
||||||
@@ -1991,7 +1964,7 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
|
|||||||
// The method writes all (header-and-body-valid) blocks to disk, then tries to
|
// The method writes all (header-and-body-valid) blocks to disk, then tries to
|
||||||
// switch over to the new chain if the TD exceeded the current chain.
|
// switch over to the new chain if the TD exceeded the current chain.
|
||||||
// insertSideChain is only used pre-merge.
|
// insertSideChain is only used pre-merge.
|
||||||
func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator, makeWitness bool) (*stateless.Witness, int, error) {
|
func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (int, error) {
|
||||||
var (
|
var (
|
||||||
externTd *big.Int
|
externTd *big.Int
|
||||||
current = bc.CurrentBlock()
|
current = bc.CurrentBlock()
|
||||||
@@ -2027,7 +2000,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator, ma
|
|||||||
// If someone legitimately side-mines blocks, they would still be imported as usual. However,
|
// If someone legitimately side-mines blocks, they would still be imported as usual. However,
|
||||||
// we cannot risk writing unverified blocks to disk when they obviously target the pruning
|
// we cannot risk writing unverified blocks to disk when they obviously target the pruning
|
||||||
// mechanism.
|
// mechanism.
|
||||||
return nil, it.index, errors.New("sidechain ghost-state attack")
|
return it.index, errors.New("sidechain ghost-state attack")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if externTd == nil {
|
if externTd == nil {
|
||||||
@@ -2038,7 +2011,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator, ma
|
|||||||
if !bc.HasBlock(block.Hash(), block.NumberU64()) {
|
if !bc.HasBlock(block.Hash(), block.NumberU64()) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
if err := bc.writeBlockWithoutState(block, externTd); err != nil {
|
if err := bc.writeBlockWithoutState(block, externTd); err != nil {
|
||||||
return nil, it.index, err
|
return it.index, err
|
||||||
}
|
}
|
||||||
log.Debug("Injected sidechain block", "number", block.Number(), "hash", block.Hash(),
|
log.Debug("Injected sidechain block", "number", block.Number(), "hash", block.Hash(),
|
||||||
"diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)),
|
"diff", block.Difficulty(), "elapsed", common.PrettyDuration(time.Since(start)),
|
||||||
@@ -2055,7 +2028,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator, ma
|
|||||||
for parent != nil && !bc.HasState(parent.Root) {
|
for parent != nil && !bc.HasState(parent.Root) {
|
||||||
if bc.stateRecoverable(parent.Root) {
|
if bc.stateRecoverable(parent.Root) {
|
||||||
if err := bc.triedb.Recover(parent.Root); err != nil {
|
if err := bc.triedb.Recover(parent.Root); err != nil {
|
||||||
return nil, 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -2065,7 +2038,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator, ma
|
|||||||
parent = bc.GetHeader(parent.ParentHash, parent.Number.Uint64()-1)
|
parent = bc.GetHeader(parent.ParentHash, parent.Number.Uint64()-1)
|
||||||
}
|
}
|
||||||
if parent == nil {
|
if parent == nil {
|
||||||
return nil, it.index, errors.New("missing parent")
|
return it.index, errors.New("missing parent")
|
||||||
}
|
}
|
||||||
// Import all the pruned blocks to make the state available
|
// Import all the pruned blocks to make the state available
|
||||||
var (
|
var (
|
||||||
@@ -2084,30 +2057,30 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator, ma
|
|||||||
// memory here.
|
// memory here.
|
||||||
if len(blocks) >= 2048 || memory > 64*1024*1024 {
|
if len(blocks) >= 2048 || memory > 64*1024*1024 {
|
||||||
log.Info("Importing heavy sidechain segment", "blocks", len(blocks), "start", blocks[0].NumberU64(), "end", block.NumberU64())
|
log.Info("Importing heavy sidechain segment", "blocks", len(blocks), "start", blocks[0].NumberU64(), "end", block.NumberU64())
|
||||||
if _, _, err := bc.insertChain(blocks, true, false); err != nil {
|
if _, err := bc.insertChain(blocks, true); err != nil {
|
||||||
return nil, 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
blocks, memory = blocks[:0], 0
|
blocks, memory = blocks[:0], 0
|
||||||
|
|
||||||
// If the chain is terminating, stop processing blocks
|
// If the chain is terminating, stop processing blocks
|
||||||
if bc.insertStopped() {
|
if bc.insertStopped() {
|
||||||
log.Debug("Abort during blocks processing")
|
log.Debug("Abort during blocks processing")
|
||||||
return nil, 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(blocks) > 0 {
|
if len(blocks) > 0 {
|
||||||
log.Info("Importing sidechain segment", "start", blocks[0].NumberU64(), "end", blocks[len(blocks)-1].NumberU64())
|
log.Info("Importing sidechain segment", "start", blocks[0].NumberU64(), "end", blocks[len(blocks)-1].NumberU64())
|
||||||
return bc.insertChain(blocks, true, makeWitness)
|
return bc.insertChain(blocks, true)
|
||||||
}
|
}
|
||||||
return nil, 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// recoverAncestors finds the closest ancestor with available state and re-execute
|
// recoverAncestors finds the closest ancestor with available state and re-execute
|
||||||
// all the ancestor blocks since that.
|
// all the ancestor blocks since that.
|
||||||
// recoverAncestors is only used post-merge.
|
// recoverAncestors is only used post-merge.
|
||||||
// We return the hash of the latest block that we could correctly validate.
|
// We return the hash of the latest block that we could correctly validate.
|
||||||
func (bc *BlockChain) recoverAncestors(block *types.Block, makeWitness bool) (common.Hash, error) {
|
func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error) {
|
||||||
// Gather all the sidechain hashes (full blocks may be memory heavy)
|
// Gather all the sidechain hashes (full blocks may be memory heavy)
|
||||||
var (
|
var (
|
||||||
hashes []common.Hash
|
hashes []common.Hash
|
||||||
@@ -2147,15 +2120,15 @@ func (bc *BlockChain) recoverAncestors(block *types.Block, makeWitness bool) (co
|
|||||||
} else {
|
} else {
|
||||||
b = bc.GetBlock(hashes[i], numbers[i])
|
b = bc.GetBlock(hashes[i], numbers[i])
|
||||||
}
|
}
|
||||||
if _, _, err := bc.insertChain(types.Blocks{b}, false, makeWitness && i == 0); err != nil {
|
if _, err := bc.insertChain(types.Blocks{b}, false); err != nil {
|
||||||
return b.ParentHash(), err
|
return b.ParentHash(), err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return block.Hash(), nil
|
return block.Hash(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// collectLogs collects the logs that were generated or removed during the
|
// collectLogs collects the logs that were generated or removed during
|
||||||
// processing of a block. These logs are later announced as deleted or reborn.
|
// the processing of a block. These logs are later announced as deleted or reborn.
|
||||||
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
||||||
var blobGasPrice *big.Int
|
var blobGasPrice *big.Int
|
||||||
excessBlobGas := b.ExcessBlobGas()
|
excessBlobGas := b.ExcessBlobGas()
|
||||||
@@ -2181,55 +2154,70 @@ func (bc *BlockChain) collectLogs(b *types.Block, removed bool) []*types.Log {
|
|||||||
// reorg takes two blocks, an old chain and a new chain and will reconstruct the
|
// reorg takes two blocks, an old chain and a new chain and will reconstruct the
|
||||||
// blocks and inserts them to be part of the new canonical chain and accumulates
|
// blocks and inserts them to be part of the new canonical chain and accumulates
|
||||||
// potential missing transactions and post an event about them.
|
// potential missing transactions and post an event about them.
|
||||||
//
|
|
||||||
// Note the new head block won't be processed here, callers need to handle it
|
// Note the new head block won't be processed here, callers need to handle it
|
||||||
// externally.
|
// externally.
|
||||||
func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error {
|
func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
||||||
var (
|
var (
|
||||||
newChain []*types.Header
|
newChain types.Blocks
|
||||||
oldChain []*types.Header
|
oldChain types.Blocks
|
||||||
commonBlock *types.Header
|
commonBlock *types.Block
|
||||||
|
|
||||||
|
deletedTxs []common.Hash
|
||||||
|
addedTxs []common.Hash
|
||||||
)
|
)
|
||||||
|
oldBlock := bc.GetBlock(oldHead.Hash(), oldHead.Number.Uint64())
|
||||||
|
if oldBlock == nil {
|
||||||
|
return errors.New("current head block missing")
|
||||||
|
}
|
||||||
|
newBlock := newHead
|
||||||
|
|
||||||
// Reduce the longer chain to the same number as the shorter one
|
// Reduce the longer chain to the same number as the shorter one
|
||||||
if oldHead.Number.Uint64() > newHead.Number.Uint64() {
|
if oldBlock.NumberU64() > newBlock.NumberU64() {
|
||||||
// Old chain is longer, gather all transactions and logs as deleted ones
|
// Old chain is longer, gather all transactions and logs as deleted ones
|
||||||
for ; oldHead != nil && oldHead.Number.Uint64() != newHead.Number.Uint64(); oldHead = bc.GetHeader(oldHead.ParentHash, oldHead.Number.Uint64()-1) {
|
for ; oldBlock != nil && oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1) {
|
||||||
oldChain = append(oldChain, oldHead)
|
oldChain = append(oldChain, oldBlock)
|
||||||
|
for _, tx := range oldBlock.Transactions() {
|
||||||
|
deletedTxs = append(deletedTxs, tx.Hash())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// New chain is longer, stash all blocks away for subsequent insertion
|
// New chain is longer, stash all blocks away for subsequent insertion
|
||||||
for ; newHead != nil && newHead.Number.Uint64() != oldHead.Number.Uint64(); newHead = bc.GetHeader(newHead.ParentHash, newHead.Number.Uint64()-1) {
|
for ; newBlock != nil && newBlock.NumberU64() != oldBlock.NumberU64(); newBlock = bc.GetBlock(newBlock.ParentHash(), newBlock.NumberU64()-1) {
|
||||||
newChain = append(newChain, newHead)
|
newChain = append(newChain, newBlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if oldHead == nil {
|
if oldBlock == nil {
|
||||||
return errInvalidOldChain
|
return errInvalidOldChain
|
||||||
}
|
}
|
||||||
if newHead == nil {
|
if newBlock == nil {
|
||||||
return errInvalidNewChain
|
return errInvalidNewChain
|
||||||
}
|
}
|
||||||
// Both sides of the reorg are at the same number, reduce both until the common
|
// Both sides of the reorg are at the same number, reduce both until the common
|
||||||
// ancestor is found
|
// ancestor is found
|
||||||
for {
|
for {
|
||||||
// If the common ancestor was found, bail out
|
// If the common ancestor was found, bail out
|
||||||
if oldHead.Hash() == newHead.Hash() {
|
if oldBlock.Hash() == newBlock.Hash() {
|
||||||
commonBlock = oldHead
|
commonBlock = oldBlock
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// Remove an old block as well as stash away a new block
|
// Remove an old block as well as stash away a new block
|
||||||
oldChain = append(oldChain, oldHead)
|
oldChain = append(oldChain, oldBlock)
|
||||||
newChain = append(newChain, newHead)
|
for _, tx := range oldBlock.Transactions() {
|
||||||
|
deletedTxs = append(deletedTxs, tx.Hash())
|
||||||
|
}
|
||||||
|
newChain = append(newChain, newBlock)
|
||||||
|
|
||||||
// Step back with both chains
|
// Step back with both chains
|
||||||
oldHead = bc.GetHeader(oldHead.ParentHash, oldHead.Number.Uint64()-1)
|
oldBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1)
|
||||||
if oldHead == nil {
|
if oldBlock == nil {
|
||||||
return errInvalidOldChain
|
return errInvalidOldChain
|
||||||
}
|
}
|
||||||
newHead = bc.GetHeader(newHead.ParentHash, newHead.Number.Uint64()-1)
|
newBlock = bc.GetBlock(newBlock.ParentHash(), newBlock.NumberU64()-1)
|
||||||
if newHead == nil {
|
if newBlock == nil {
|
||||||
return errInvalidNewChain
|
return errInvalidNewChain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the user sees large reorgs
|
// Ensure the user sees large reorgs
|
||||||
if len(oldChain) > 0 && len(newChain) > 0 {
|
if len(oldChain) > 0 && len(newChain) > 0 {
|
||||||
logFn := log.Info
|
logFn := log.Info
|
||||||
@@ -2238,7 +2226,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error
|
|||||||
msg = "Large chain reorg detected"
|
msg = "Large chain reorg detected"
|
||||||
logFn = log.Warn
|
logFn = log.Warn
|
||||||
}
|
}
|
||||||
logFn(msg, "number", commonBlock.Number, "hash", commonBlock.Hash(),
|
logFn(msg, "number", commonBlock.Number(), "hash", commonBlock.Hash(),
|
||||||
"drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash())
|
"drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash())
|
||||||
blockReorgAddMeter.Mark(int64(len(newChain)))
|
blockReorgAddMeter.Mark(int64(len(newChain)))
|
||||||
blockReorgDropMeter.Mark(int64(len(oldChain)))
|
blockReorgDropMeter.Mark(int64(len(oldChain)))
|
||||||
@@ -2246,112 +2234,55 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error
|
|||||||
} else if len(newChain) > 0 {
|
} else if len(newChain) > 0 {
|
||||||
// Special case happens in the post merge stage that current head is
|
// Special case happens in the post merge stage that current head is
|
||||||
// the ancestor of new head while these two blocks are not consecutive
|
// the ancestor of new head while these two blocks are not consecutive
|
||||||
log.Info("Extend chain", "add", len(newChain), "number", newChain[0].Number, "hash", newChain[0].Hash())
|
log.Info("Extend chain", "add", len(newChain), "number", newChain[0].Number(), "hash", newChain[0].Hash())
|
||||||
blockReorgAddMeter.Mark(int64(len(newChain)))
|
blockReorgAddMeter.Mark(int64(len(newChain)))
|
||||||
} else {
|
} else {
|
||||||
// len(newChain) == 0 && len(oldChain) > 0
|
// len(newChain) == 0 && len(oldChain) > 0
|
||||||
// rewind the canonical chain to a lower point.
|
// rewind the canonical chain to a lower point.
|
||||||
log.Error("Impossible reorg, please file an issue", "oldnum", oldHead.Number, "oldhash", oldHead.Hash(), "oldblocks", len(oldChain), "newnum", newHead.Number, "newhash", newHead.Hash(), "newblocks", len(newChain))
|
log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "oldblocks", len(oldChain), "newnum", newBlock.Number(), "newhash", newBlock.Hash(), "newblocks", len(newChain))
|
||||||
}
|
}
|
||||||
// Acquire the tx-lookup lock before mutation. This step is essential
|
// Acquire the tx-lookup lock before mutation. This step is essential
|
||||||
// as the txlookups should be changed atomically, and all subsequent
|
// as the txlookups should be changed atomically, and all subsequent
|
||||||
// reads should be blocked until the mutation is complete.
|
// reads should be blocked until the mutation is complete.
|
||||||
bc.txLookupLock.Lock()
|
bc.txLookupLock.Lock()
|
||||||
|
|
||||||
// Reorg can be executed, start reducing the chain's old blocks and appending
|
// Insert the new chain segment in incremental order, from the old
|
||||||
// the new blocks
|
// to the new. The new chain head (newChain[0]) is not inserted here,
|
||||||
var (
|
// as it will be handled separately outside of this function
|
||||||
deletedTxs []common.Hash
|
|
||||||
rebirthTxs []common.Hash
|
|
||||||
|
|
||||||
deletedLogs []*types.Log
|
|
||||||
rebirthLogs []*types.Log
|
|
||||||
)
|
|
||||||
// Deleted log emission on the API uses forward order, which is borked, but
|
|
||||||
// we'll leave it in for legacy reasons.
|
|
||||||
//
|
|
||||||
// TODO(karalabe): This should be nuked out, no idea how, deprecate some APIs?
|
|
||||||
{
|
|
||||||
for i := len(oldChain) - 1; i >= 0; i-- {
|
|
||||||
block := bc.GetBlock(oldChain[i].Hash(), oldChain[i].Number.Uint64())
|
|
||||||
if block == nil {
|
|
||||||
return errInvalidOldChain // Corrupt database, mostly here to avoid weird panics
|
|
||||||
}
|
|
||||||
if logs := bc.collectLogs(block, true); len(logs) > 0 {
|
|
||||||
deletedLogs = append(deletedLogs, logs...)
|
|
||||||
}
|
|
||||||
if len(deletedLogs) > 512 {
|
|
||||||
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
|
|
||||||
deletedLogs = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(deletedLogs) > 0 {
|
|
||||||
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Undo old blocks in reverse order
|
|
||||||
for i := 0; i < len(oldChain); i++ {
|
|
||||||
// Collect all the deleted transactions
|
|
||||||
block := bc.GetBlock(oldChain[i].Hash(), oldChain[i].Number.Uint64())
|
|
||||||
if block == nil {
|
|
||||||
return errInvalidOldChain // Corrupt database, mostly here to avoid weird panics
|
|
||||||
}
|
|
||||||
for _, tx := range block.Transactions() {
|
|
||||||
deletedTxs = append(deletedTxs, tx.Hash())
|
|
||||||
}
|
|
||||||
// Collect deleted logs and emit them for new integrations
|
|
||||||
if logs := bc.collectLogs(block, true); len(logs) > 0 {
|
|
||||||
// Emit revertals latest first, older then
|
|
||||||
slices.Reverse(logs)
|
|
||||||
|
|
||||||
// TODO(karalabe): Hook into the reverse emission part
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Apply new blocks in forward order
|
|
||||||
for i := len(newChain) - 1; i >= 1; i-- {
|
for i := len(newChain) - 1; i >= 1; i-- {
|
||||||
// Collect all the included transactions
|
// Insert the block in the canonical way, re-writing history
|
||||||
block := bc.GetBlock(newChain[i].Hash(), newChain[i].Number.Uint64())
|
bc.writeHeadBlock(newChain[i])
|
||||||
if block == nil {
|
|
||||||
return errInvalidNewChain // Corrupt database, mostly here to avoid weird panics
|
// Collect the new added transactions.
|
||||||
|
for _, tx := range newChain[i].Transactions() {
|
||||||
|
addedTxs = append(addedTxs, tx.Hash())
|
||||||
}
|
}
|
||||||
for _, tx := range block.Transactions() {
|
|
||||||
rebirthTxs = append(rebirthTxs, tx.Hash())
|
|
||||||
}
|
|
||||||
// Collect inserted logs and emit them
|
|
||||||
if logs := bc.collectLogs(block, false); len(logs) > 0 {
|
|
||||||
rebirthLogs = append(rebirthLogs, logs...)
|
|
||||||
}
|
|
||||||
if len(rebirthLogs) > 512 {
|
|
||||||
bc.logsFeed.Send(rebirthLogs)
|
|
||||||
rebirthLogs = nil
|
|
||||||
}
|
|
||||||
// Update the head block
|
|
||||||
bc.writeHeadBlock(block)
|
|
||||||
}
|
|
||||||
if len(rebirthLogs) > 0 {
|
|
||||||
bc.logsFeed.Send(rebirthLogs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete useless indexes right now which includes the non-canonical
|
// Delete useless indexes right now which includes the non-canonical
|
||||||
// transaction indexes, canonical chain indexes which above the head.
|
// transaction indexes, canonical chain indexes which above the head.
|
||||||
batch := bc.db.NewBatch()
|
var (
|
||||||
for _, tx := range types.HashDifference(deletedTxs, rebirthTxs) {
|
indexesBatch = bc.db.NewBatch()
|
||||||
rawdb.DeleteTxLookupEntry(batch, tx)
|
diffs = types.HashDifference(deletedTxs, addedTxs)
|
||||||
|
)
|
||||||
|
for _, tx := range diffs {
|
||||||
|
rawdb.DeleteTxLookupEntry(indexesBatch, tx)
|
||||||
}
|
}
|
||||||
// Delete all hash markers that are not part of the new canonical chain.
|
// Delete all hash markers that are not part of the new canonical chain.
|
||||||
// Because the reorg function does not handle new chain head, all hash
|
// Because the reorg function does not handle new chain head, all hash
|
||||||
// markers greater than or equal to new chain head should be deleted.
|
// markers greater than or equal to new chain head should be deleted.
|
||||||
number := commonBlock.Number
|
number := commonBlock.NumberU64()
|
||||||
if len(newChain) > 1 {
|
if len(newChain) > 1 {
|
||||||
number = newChain[1].Number
|
number = newChain[1].NumberU64()
|
||||||
}
|
}
|
||||||
for i := number.Uint64() + 1; ; i++ {
|
for i := number + 1; ; i++ {
|
||||||
hash := rawdb.ReadCanonicalHash(bc.db, i)
|
hash := rawdb.ReadCanonicalHash(bc.db, i)
|
||||||
if hash == (common.Hash{}) {
|
if hash == (common.Hash{}) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
rawdb.DeleteCanonicalHash(batch, i)
|
rawdb.DeleteCanonicalHash(indexesBatch, i)
|
||||||
}
|
}
|
||||||
if err := batch.Write(); err != nil {
|
if err := indexesBatch.Write(); err != nil {
|
||||||
log.Crit("Failed to delete useless indexes", "err", err)
|
log.Crit("Failed to delete useless indexes", "err", err)
|
||||||
}
|
}
|
||||||
// Reset the tx lookup cache to clear stale txlookup cache.
|
// Reset the tx lookup cache to clear stale txlookup cache.
|
||||||
@@ -2360,6 +2291,43 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error
|
|||||||
// Release the tx-lookup lock after mutation.
|
// Release the tx-lookup lock after mutation.
|
||||||
bc.txLookupLock.Unlock()
|
bc.txLookupLock.Unlock()
|
||||||
|
|
||||||
|
// Send out events for logs from the old canon chain, and 'reborn'
|
||||||
|
// logs from the new canon chain. The number of logs can be very
|
||||||
|
// high, so the events are sent in batches of size around 512.
|
||||||
|
|
||||||
|
// Deleted logs + blocks:
|
||||||
|
var deletedLogs []*types.Log
|
||||||
|
for i := len(oldChain) - 1; i >= 0; i-- {
|
||||||
|
// Also send event for blocks removed from the canon chain.
|
||||||
|
bc.chainSideFeed.Send(ChainSideEvent{Block: oldChain[i]})
|
||||||
|
|
||||||
|
// Collect deleted logs for notification
|
||||||
|
if logs := bc.collectLogs(oldChain[i], true); len(logs) > 0 {
|
||||||
|
deletedLogs = append(deletedLogs, logs...)
|
||||||
|
}
|
||||||
|
if len(deletedLogs) > 512 {
|
||||||
|
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
|
||||||
|
deletedLogs = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(deletedLogs) > 0 {
|
||||||
|
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
|
||||||
|
}
|
||||||
|
|
||||||
|
// New logs:
|
||||||
|
var rebirthLogs []*types.Log
|
||||||
|
for i := len(newChain) - 1; i >= 1; i-- {
|
||||||
|
if logs := bc.collectLogs(newChain[i], false); len(logs) > 0 {
|
||||||
|
rebirthLogs = append(rebirthLogs, logs...)
|
||||||
|
}
|
||||||
|
if len(rebirthLogs) > 512 {
|
||||||
|
bc.logsFeed.Send(rebirthLogs)
|
||||||
|
rebirthLogs = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(rebirthLogs) > 0 {
|
||||||
|
bc.logsFeed.Send(rebirthLogs)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2368,14 +2336,14 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error
|
|||||||
// The key difference between the InsertChain is it won't do the canonical chain
|
// The key difference between the InsertChain is it won't do the canonical chain
|
||||||
// updating. It relies on the additional SetCanonical call to finalize the entire
|
// updating. It relies on the additional SetCanonical call to finalize the entire
|
||||||
// procedure.
|
// procedure.
|
||||||
func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block, makeWitness bool) (*stateless.Witness, error) {
|
func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block) error {
|
||||||
if !bc.chainmu.TryLock() {
|
if !bc.chainmu.TryLock() {
|
||||||
return nil, errChainStopped
|
return errChainStopped
|
||||||
}
|
}
|
||||||
defer bc.chainmu.Unlock()
|
defer bc.chainmu.Unlock()
|
||||||
|
|
||||||
witness, _, err := bc.insertChain(types.Blocks{block}, false, makeWitness)
|
_, err := bc.insertChain(types.Blocks{block}, false)
|
||||||
return witness, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCanonical rewinds the chain to set the new head block as the specified
|
// SetCanonical rewinds the chain to set the new head block as the specified
|
||||||
@@ -2389,7 +2357,7 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
|
|||||||
|
|
||||||
// Re-execute the reorged chain in case the head state is missing.
|
// Re-execute the reorged chain in case the head state is missing.
|
||||||
if !bc.HasState(head.Root()) {
|
if !bc.HasState(head.Root()) {
|
||||||
if latestValidHash, err := bc.recoverAncestors(head, false); err != nil {
|
if latestValidHash, err := bc.recoverAncestors(head); err != nil {
|
||||||
return latestValidHash, err
|
return latestValidHash, err
|
||||||
}
|
}
|
||||||
log.Info("Recovered head state", "number", head.Number(), "hash", head.Hash())
|
log.Info("Recovered head state", "number", head.Number(), "hash", head.Hash())
|
||||||
@@ -2397,7 +2365,7 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
|
|||||||
// Run the reorg if necessary and set the given block as new head.
|
// Run the reorg if necessary and set the given block as new head.
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
if head.ParentHash() != bc.CurrentBlock().Hash() {
|
if head.ParentHash() != bc.CurrentBlock().Hash() {
|
||||||
if err := bc.reorg(bc.CurrentBlock(), head.Header()); err != nil {
|
if err := bc.reorg(bc.CurrentBlock(), head); err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2405,11 +2373,11 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
|
|||||||
|
|
||||||
// Emit events
|
// Emit events
|
||||||
logs := bc.collectLogs(head, false)
|
logs := bc.collectLogs(head, false)
|
||||||
bc.chainFeed.Send(ChainEvent{Header: head.Header()})
|
bc.chainFeed.Send(ChainEvent{Block: head, Hash: head.Hash(), Logs: logs})
|
||||||
if len(logs) > 0 {
|
if len(logs) > 0 {
|
||||||
bc.logsFeed.Send(logs)
|
bc.logsFeed.Send(logs)
|
||||||
}
|
}
|
||||||
bc.chainHeadFeed.Send(ChainHeadEvent{Header: head.Header()})
|
bc.chainHeadFeed.Send(ChainHeadEvent{Block: head})
|
||||||
|
|
||||||
context := []interface{}{
|
context := []interface{}{
|
||||||
"number", head.Number(),
|
"number", head.Number(),
|
||||||
|
|||||||
@@ -430,6 +430,11 @@ func (bc *BlockChain) SubscribeChainHeadEvent(ch chan<- ChainHeadEvent) event.Su
|
|||||||
return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
|
return bc.scope.Track(bc.chainHeadFeed.Subscribe(ch))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SubscribeChainSideEvent registers a subscription of ChainSideEvent.
|
||||||
|
func (bc *BlockChain) SubscribeChainSideEvent(ch chan<- ChainSideEvent) event.Subscription {
|
||||||
|
return bc.scope.Track(bc.chainSideFeed.Subscribe(ch))
|
||||||
|
}
|
||||||
|
|
||||||
// SubscribeLogsEvent registers a subscription of []*types.Log.
|
// SubscribeLogsEvent registers a subscription of []*types.Log.
|
||||||
func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
|
func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
|
||||||
return bc.scope.Track(bc.logsFeed.Subscribe(ch))
|
return bc.scope.Track(bc.logsFeed.Subscribe(ch))
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1758,20 +1757,20 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
|
|||||||
|
|
||||||
func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
|
func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||||
// fmt.Println(tt.dump(false))
|
// fmt.Println(tt.dump(true))
|
||||||
|
|
||||||
// Create a temporary persistent database
|
// Create a temporary persistent database
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
db, err := rawdb.Open(rawdb.OpenOptions{
|
||||||
|
Directory: datadir,
|
||||||
|
AncientsDirectory: ancient,
|
||||||
|
Ephemeral: true,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent database: %v", err)
|
||||||
}
|
|
||||||
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
|
||||||
}
|
}
|
||||||
defer db.Close() // Might double close, should be fine
|
defer db.Close() // Might double close, should be fine
|
||||||
|
|
||||||
@@ -1850,13 +1849,13 @@ func testRepairWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme s
|
|||||||
chain.stopWithoutSaving()
|
chain.stopWithoutSaving()
|
||||||
|
|
||||||
// Start a new blockchain back up and see where the repair leads us
|
// Start a new blockchain back up and see where the repair leads us
|
||||||
pdb, err = pebble.New(datadir, 0, 0, "", false)
|
db, err = rawdb.Open(rawdb.OpenOptions{
|
||||||
|
Directory: datadir,
|
||||||
|
AncientsDirectory: ancient,
|
||||||
|
Ephemeral: true,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to reopen persistent key-value database: %v", err)
|
t.Fatalf("Failed to reopen persistent database: %v", err)
|
||||||
}
|
|
||||||
db, err = rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to reopen persistent freezer database: %v", err)
|
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
@@ -1909,19 +1908,18 @@ func TestIssue23496(t *testing.T) {
|
|||||||
|
|
||||||
func testIssue23496(t *testing.T, scheme string) {
|
func testIssue23496(t *testing.T, scheme string) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||||
|
|
||||||
// Create a temporary persistent database
|
// Create a temporary persistent database
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
db, err := rawdb.Open(rawdb.OpenOptions{
|
||||||
|
Directory: datadir,
|
||||||
|
AncientsDirectory: ancient,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent database: %v", err)
|
||||||
}
|
|
||||||
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
|
||||||
}
|
}
|
||||||
defer db.Close() // Might double close, should be fine
|
defer db.Close() // Might double close, should be fine
|
||||||
|
|
||||||
@@ -1973,13 +1971,13 @@ func testIssue23496(t *testing.T, scheme string) {
|
|||||||
chain.stopWithoutSaving()
|
chain.stopWithoutSaving()
|
||||||
|
|
||||||
// Start a new blockchain back up and see where the repair leads us
|
// Start a new blockchain back up and see where the repair leads us
|
||||||
pdb, err = pebble.New(datadir, 0, 0, "", false)
|
db, err = rawdb.Open(rawdb.OpenOptions{
|
||||||
|
Directory: datadir,
|
||||||
|
AncientsDirectory: ancient,
|
||||||
|
Ephemeral: true,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to reopen persistent key-value database: %v", err)
|
t.Fatalf("Failed to reopen persistent database: %v", err)
|
||||||
}
|
|
||||||
db, err = rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to reopen persistent freezer database: %v", err)
|
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/triedb"
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
"github.com/ethereum/go-ethereum/triedb/hashdb"
|
||||||
@@ -1962,20 +1961,20 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
|
|||||||
|
|
||||||
func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
|
func testSetHeadWithScheme(t *testing.T, tt *rewindTest, snapshots bool, scheme string) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||||
// fmt.Println(tt.dump(false))
|
// fmt.Println(tt.dump(false))
|
||||||
|
|
||||||
// Create a temporary persistent database
|
// Create a temporary persistent database
|
||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
db, err := rawdb.Open(rawdb.OpenOptions{
|
||||||
|
Directory: datadir,
|
||||||
|
AncientsDirectory: ancient,
|
||||||
|
Ephemeral: true,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent database: %v", err)
|
||||||
}
|
|
||||||
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -66,13 +65,13 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
|
|||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := filepath.Join(datadir, "ancient")
|
ancient := filepath.Join(datadir, "ancient")
|
||||||
|
|
||||||
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
db, err := rawdb.Open(rawdb.OpenOptions{
|
||||||
|
Directory: datadir,
|
||||||
|
AncientsDirectory: ancient,
|
||||||
|
Ephemeral: true,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent database: %v", err)
|
||||||
}
|
|
||||||
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
|
||||||
}
|
}
|
||||||
// Initialize a fresh chain
|
// Initialize a fresh chain
|
||||||
var (
|
var (
|
||||||
@@ -223,8 +222,8 @@ type snapshotTest struct {
|
|||||||
|
|
||||||
func (snaptest *snapshotTest) test(t *testing.T) {
|
func (snaptest *snapshotTest) test(t *testing.T) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||||
// fmt.Println(snaptest.dump())
|
// fmt.Println(tt.dump())
|
||||||
chain, blocks := snaptest.prepare(t)
|
chain, blocks := snaptest.prepare(t)
|
||||||
|
|
||||||
// Restart the chain normally
|
// Restart the chain normally
|
||||||
@@ -246,8 +245,8 @@ type crashSnapshotTest struct {
|
|||||||
|
|
||||||
func (snaptest *crashSnapshotTest) test(t *testing.T) {
|
func (snaptest *crashSnapshotTest) test(t *testing.T) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||||
// fmt.Println(snaptest.dump())
|
// fmt.Println(tt.dump())
|
||||||
chain, blocks := snaptest.prepare(t)
|
chain, blocks := snaptest.prepare(t)
|
||||||
|
|
||||||
// Pull the plug on the database, simulating a hard crash
|
// Pull the plug on the database, simulating a hard crash
|
||||||
@@ -257,13 +256,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
|
|||||||
chain.triedb.Close()
|
chain.triedb.Close()
|
||||||
|
|
||||||
// Start a new blockchain back up and see where the repair leads us
|
// Start a new blockchain back up and see where the repair leads us
|
||||||
pdb, err := pebble.New(snaptest.datadir, 0, 0, "", false)
|
newdb, err := rawdb.Open(rawdb.OpenOptions{
|
||||||
|
Directory: snaptest.datadir,
|
||||||
|
AncientsDirectory: snaptest.ancient,
|
||||||
|
Ephemeral: true,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to reopen persistent database: %v", err)
|
||||||
}
|
|
||||||
newdb, err := rawdb.NewDatabaseWithFreezer(pdb, snaptest.ancient, "", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
|
||||||
}
|
}
|
||||||
defer newdb.Close()
|
defer newdb.Close()
|
||||||
|
|
||||||
@@ -298,8 +297,8 @@ type gappedSnapshotTest struct {
|
|||||||
|
|
||||||
func (snaptest *gappedSnapshotTest) test(t *testing.T) {
|
func (snaptest *gappedSnapshotTest) test(t *testing.T) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||||
// fmt.Println(snaptest.dump())
|
// fmt.Println(tt.dump())
|
||||||
chain, blocks := snaptest.prepare(t)
|
chain, blocks := snaptest.prepare(t)
|
||||||
|
|
||||||
// Insert blocks without enabling snapshot if gapping is required.
|
// Insert blocks without enabling snapshot if gapping is required.
|
||||||
@@ -342,8 +341,8 @@ type setHeadSnapshotTest struct {
|
|||||||
|
|
||||||
func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
|
func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||||
// fmt.Println(snaptest.dump())
|
// fmt.Println(tt.dump())
|
||||||
chain, blocks := snaptest.prepare(t)
|
chain, blocks := snaptest.prepare(t)
|
||||||
|
|
||||||
// Rewind the chain if setHead operation is required.
|
// Rewind the chain if setHead operation is required.
|
||||||
@@ -371,8 +370,8 @@ type wipeCrashSnapshotTest struct {
|
|||||||
|
|
||||||
func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
||||||
// It's hard to follow the test case, visualize the input
|
// It's hard to follow the test case, visualize the input
|
||||||
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
// log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||||
// fmt.Println(snaptest.dump())
|
// fmt.Println(tt.dump())
|
||||||
chain, blocks := snaptest.prepare(t)
|
chain, blocks := snaptest.prepare(t)
|
||||||
|
|
||||||
// Firstly, stop the chain properly, with all snapshot journal
|
// Firstly, stop the chain properly, with all snapshot journal
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package core
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
gomath "math"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
@@ -29,6 +28,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/beacon"
|
"github.com/ethereum/go-ethereum/consensus/beacon"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
@@ -39,7 +39,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
@@ -1333,6 +1332,85 @@ func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan Re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReorgSideEvent(t *testing.T) {
|
||||||
|
testReorgSideEvent(t, rawdb.HashScheme)
|
||||||
|
testReorgSideEvent(t, rawdb.PathScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testReorgSideEvent(t *testing.T, scheme string) {
|
||||||
|
var (
|
||||||
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: params.TestChainConfig,
|
||||||
|
Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}},
|
||||||
|
}
|
||||||
|
signer = types.LatestSigner(gspec.Config)
|
||||||
|
)
|
||||||
|
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||||
|
defer blockchain.Stop()
|
||||||
|
|
||||||
|
_, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, gen *BlockGen) {})
|
||||||
|
if _, err := blockchain.InsertChain(chain); err != nil {
|
||||||
|
t.Fatalf("failed to insert chain: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, replacementBlocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 4, func(i int, gen *BlockGen) {
|
||||||
|
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, nil), signer, key1)
|
||||||
|
if i == 2 {
|
||||||
|
gen.OffsetTime(-9)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create tx: %v", err)
|
||||||
|
}
|
||||||
|
gen.AddTx(tx)
|
||||||
|
})
|
||||||
|
chainSideCh := make(chan ChainSideEvent, 64)
|
||||||
|
blockchain.SubscribeChainSideEvent(chainSideCh)
|
||||||
|
if _, err := blockchain.InsertChain(replacementBlocks); err != nil {
|
||||||
|
t.Fatalf("failed to insert chain: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedSideHashes := map[common.Hash]bool{
|
||||||
|
chain[0].Hash(): true,
|
||||||
|
chain[1].Hash(): true,
|
||||||
|
chain[2].Hash(): true,
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
|
||||||
|
const timeoutDura = 10 * time.Second
|
||||||
|
timeout := time.NewTimer(timeoutDura)
|
||||||
|
done:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case ev := <-chainSideCh:
|
||||||
|
block := ev.Block
|
||||||
|
if _, ok := expectedSideHashes[block.Hash()]; !ok {
|
||||||
|
t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash())
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
|
||||||
|
if i == len(expectedSideHashes) {
|
||||||
|
timeout.Stop()
|
||||||
|
|
||||||
|
break done
|
||||||
|
}
|
||||||
|
timeout.Reset(timeoutDura)
|
||||||
|
|
||||||
|
case <-timeout.C:
|
||||||
|
t.Fatalf("Timeout. Possibly not all blocks were triggered for sideevent: %v", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure no more events are fired
|
||||||
|
select {
|
||||||
|
case e := <-chainSideCh:
|
||||||
|
t.Errorf("unexpected event fired: %v", e)
|
||||||
|
case <-time.After(250 * time.Millisecond):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tests if the canonical block can be fetched from the database during chain insertion.
|
// Tests if the canonical block can be fetched from the database during chain insertion.
|
||||||
func TestCanonicalBlockRetrieval(t *testing.T) {
|
func TestCanonicalBlockRetrieval(t *testing.T) {
|
||||||
testCanonicalBlockRetrieval(t, rawdb.HashScheme)
|
testCanonicalBlockRetrieval(t, rawdb.HashScheme)
|
||||||
@@ -1950,11 +2028,11 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
|||||||
|
|
||||||
gspec = &Genesis{
|
gspec = &Genesis{
|
||||||
Config: &chainConfig,
|
Config: &chainConfig,
|
||||||
Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(gomath.MaxInt64)}},
|
Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
}
|
}
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
mergeBlock = gomath.MaxInt32
|
mergeBlock = math.MaxInt32
|
||||||
)
|
)
|
||||||
// Generate and import the canonical chain
|
// Generate and import the canonical chain
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
||||||
@@ -2048,9 +2126,9 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
|||||||
// [ Cn, Cn+1, Cc, Sn+3 ... Sm]
|
// [ Cn, Cn+1, Cc, Sn+3 ... Sm]
|
||||||
// ^ ^ ^ pruned
|
// ^ ^ ^ pruned
|
||||||
func TestPrunedImportSide(t *testing.T) {
|
func TestPrunedImportSide(t *testing.T) {
|
||||||
// glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false))
|
//glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false)))
|
||||||
// glogger.Verbosity(3)
|
//glogger.Verbosity(3)
|
||||||
// log.SetDefault(log.NewLogger(glogger))
|
//log.Root().SetHandler(log.Handler(glogger))
|
||||||
testSideImport(t, 3, 3, -1)
|
testSideImport(t, 3, 3, -1)
|
||||||
testSideImport(t, 3, -3, -1)
|
testSideImport(t, 3, -3, -1)
|
||||||
testSideImport(t, 10, 0, -1)
|
testSideImport(t, 10, 0, -1)
|
||||||
@@ -2059,9 +2137,9 @@ func TestPrunedImportSide(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPrunedImportSideWithMerging(t *testing.T) {
|
func TestPrunedImportSideWithMerging(t *testing.T) {
|
||||||
// glogger := log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false))
|
//glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false)))
|
||||||
// glogger.Verbosity(3)
|
//glogger.Verbosity(3)
|
||||||
// log.SetDefault(log.NewLogger(glogger))
|
//log.Root().SetHandler(log.Handler(glogger))
|
||||||
testSideImport(t, 3, 3, 0)
|
testSideImport(t, 3, 3, 0)
|
||||||
testSideImport(t, 3, -3, 0)
|
testSideImport(t, 3, -3, 0)
|
||||||
testSideImport(t, 10, 0, 0)
|
testSideImport(t, 10, 0, 0)
|
||||||
@@ -2237,7 +2315,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
|
|||||||
Config: &chainConfig,
|
Config: &chainConfig,
|
||||||
}
|
}
|
||||||
engine = beacon.New(ethash.NewFaker())
|
engine = beacon.New(ethash.NewFaker())
|
||||||
mergeBlock = uint64(gomath.MaxUint64)
|
mergeBlock = uint64(math.MaxUint64)
|
||||||
)
|
)
|
||||||
// Apply merging since genesis
|
// Apply merging since genesis
|
||||||
if mergeHeight == 0 {
|
if mergeHeight == 0 {
|
||||||
@@ -2663,13 +2741,13 @@ func testSideImportPrunedBlocks(t *testing.T, scheme string) {
|
|||||||
datadir := t.TempDir()
|
datadir := t.TempDir()
|
||||||
ancient := path.Join(datadir, "ancient")
|
ancient := path.Join(datadir, "ancient")
|
||||||
|
|
||||||
pdb, err := pebble.New(datadir, 0, 0, "", false)
|
db, err := rawdb.Open(rawdb.OpenOptions{
|
||||||
|
Directory: datadir,
|
||||||
|
AncientsDirectory: ancient,
|
||||||
|
Ephemeral: true,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create persistent key-value database: %v", err)
|
t.Fatalf("Failed to create persistent database: %v", err)
|
||||||
}
|
|
||||||
db, err := rawdb.NewDatabaseWithFreezer(pdb, ancient, "", false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to create persistent freezer database: %v", err)
|
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
@@ -3551,7 +3629,7 @@ func TestSetCanonical(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testSetCanonical(t *testing.T, scheme string) {
|
func testSetCanonical(t *testing.T, scheme string) {
|
||||||
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
|
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||||
|
|
||||||
var (
|
var (
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
@@ -3596,7 +3674,7 @@ func testSetCanonical(t *testing.T, scheme string) {
|
|||||||
gen.AddTx(tx)
|
gen.AddTx(tx)
|
||||||
})
|
})
|
||||||
for _, block := range side {
|
for _, block := range side {
|
||||||
_, err := chain.InsertBlockWithoutSetHead(block, false)
|
err := chain.InsertBlockWithoutSetHead(block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to insert into chain: %v", err)
|
t.Fatalf("Failed to insert into chain: %v", err)
|
||||||
}
|
}
|
||||||
@@ -4093,6 +4171,7 @@ func TestEIP3651(t *testing.T) {
|
|||||||
gspec.Config.BerlinBlock = common.Big0
|
gspec.Config.BerlinBlock = common.Big0
|
||||||
gspec.Config.LondonBlock = common.Big0
|
gspec.Config.LondonBlock = common.Big0
|
||||||
gspec.Config.TerminalTotalDifficulty = common.Big0
|
gspec.Config.TerminalTotalDifficulty = common.Big0
|
||||||
|
gspec.Config.TerminalTotalDifficultyPassed = true
|
||||||
gspec.Config.ShanghaiTime = u64(0)
|
gspec.Config.ShanghaiTime = u64(0)
|
||||||
signer := types.LatestSigner(gspec.Config)
|
signer := types.LatestSigner(gspec.Config)
|
||||||
|
|
||||||
@@ -4149,81 +4228,56 @@ func TestEIP3651(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple deposit generator, source: https://gist.github.com/lightclient/54abb2af2465d6969fa6d1920b9ad9d7
|
func TestEIP6110(t *testing.T) {
|
||||||
var depositsGeneratorCode = common.FromHex("6080604052366103aa575f603067ffffffffffffffff811115610025576100246103ae565b5b6040519080825280601f01601f1916602001820160405280156100575781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061007d5761007c6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f602067ffffffffffffffff8111156100c7576100c66103ae565b5b6040519080825280601f01601f1916602001820160405280156100f95781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061011f5761011e6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff811115610169576101686103ae565b5b6040519080825280601f01601f19166020018201604052801561019b5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f815181106101c1576101c06103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f606067ffffffffffffffff81111561020b5761020a6103ae565b5b6040519080825280601f01601f19166020018201604052801561023d5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610263576102626103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff8111156102ad576102ac6103ae565b5b6040519080825280601f01601f1916602001820160405280156102df5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610305576103046103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f8081819054906101000a900460ff168092919061035090610441565b91906101000a81548160ff021916908360ff160217905550507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c585858585856040516103a09594939291906104d9565b60405180910390a1005b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60ff82169050919050565b5f61044b82610435565b915060ff820361045e5761045d610408565b5b600182019050919050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6104ab82610469565b6104b58185610473565b93506104c5818560208601610483565b6104ce81610491565b840191505092915050565b5f60a0820190508181035f8301526104f181886104a1565b9050818103602083015261050581876104a1565b9050818103604083015261051981866104a1565b9050818103606083015261052d81856104a1565b9050818103608083015261054181846104a1565b9050969550505050505056fea26469706673582212208569967e58690162d7d6fe3513d07b393b4c15e70f41505cbbfd08f53eba739364736f6c63430008190033")
|
|
||||||
|
|
||||||
// This is a smoke test for EIP-7685 requests added in the Prague fork. The test first
|
|
||||||
// creates a block containing requests, and then inserts it into the chain to run
|
|
||||||
// validation.
|
|
||||||
func TestPragueRequests(t *testing.T) {
|
|
||||||
var (
|
var (
|
||||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
engine = beacon.NewFaker()
|
||||||
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
|
||||||
config = *params.MergedTestChainConfig
|
// A sender who makes transactions, has some funds
|
||||||
signer = types.LatestSigner(&config)
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
engine = beacon.NewFaker()
|
addr = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
|
||||||
|
config = *params.AllEthashProtocolChanges
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: &config,
|
||||||
|
Alloc: types.GenesisAlloc{
|
||||||
|
addr: {Balance: funds},
|
||||||
|
config.DepositContractAddress: {
|
||||||
|
// Simple deposit generator, source: https://gist.github.com/lightclient/54abb2af2465d6969fa6d1920b9ad9d7
|
||||||
|
Code: common.Hex2Bytes("6080604052366103aa575f603067ffffffffffffffff811115610025576100246103ae565b5b6040519080825280601f01601f1916602001820160405280156100575781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061007d5761007c6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f602067ffffffffffffffff8111156100c7576100c66103ae565b5b6040519080825280601f01601f1916602001820160405280156100f95781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f8151811061011f5761011e6103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff811115610169576101686103ae565b5b6040519080825280601f01601f19166020018201604052801561019b5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f815181106101c1576101c06103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f606067ffffffffffffffff81111561020b5761020a6103ae565b5b6040519080825280601f01601f19166020018201604052801561023d5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610263576102626103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f600867ffffffffffffffff8111156102ad576102ac6103ae565b5b6040519080825280601f01601f1916602001820160405280156102df5781602001600182028036833780820191505090505b5090505f8054906101000a900460ff1660f81b815f81518110610305576103046103db565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f8081819054906101000a900460ff168092919061035090610441565b91906101000a81548160ff021916908360ff160217905550507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c585858585856040516103a09594939291906104d9565b60405180910390a1005b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60ff82169050919050565b5f61044b82610435565b915060ff820361045e5761045d610408565b5b600182019050919050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6104ab82610469565b6104b58185610473565b93506104c5818560208601610483565b6104ce81610491565b840191505092915050565b5f60a0820190508181035f8301526104f181886104a1565b9050818103602083015261050581876104a1565b9050818103604083015261051981866104a1565b9050818103606083015261052d81856104a1565b9050818103608083015261054181846104a1565b9050969550505050505056fea26469706673582212208569967e58690162d7d6fe3513d07b393b4c15e70f41505cbbfd08f53eba739364736f6c63430008190033"),
|
||||||
|
Nonce: 0,
|
||||||
|
Balance: big.NewInt(0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
gspec := &Genesis{
|
|
||||||
Config: &config,
|
gspec.Config.BerlinBlock = common.Big0
|
||||||
Alloc: types.GenesisAlloc{
|
gspec.Config.LondonBlock = common.Big0
|
||||||
addr1: {Balance: big.NewInt(9999900000000000)},
|
gspec.Config.TerminalTotalDifficulty = common.Big0
|
||||||
config.DepositContractAddress: {Code: depositsGeneratorCode},
|
gspec.Config.TerminalTotalDifficultyPassed = true
|
||||||
params.WithdrawalQueueAddress: {Code: params.WithdrawalQueueCode},
|
gspec.Config.ShanghaiTime = u64(0)
|
||||||
params.ConsolidationQueueAddress: {Code: params.ConsolidationQueueCode},
|
gspec.Config.CancunTime = u64(0)
|
||||||
},
|
gspec.Config.PragueTime = u64(0)
|
||||||
}
|
signer := types.LatestSigner(gspec.Config)
|
||||||
|
|
||||||
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
|
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
|
||||||
// create deposit
|
for i := 0; i < 5; i++ {
|
||||||
depositTx := types.MustSignNewTx(key1, signer, &types.DynamicFeeTx{
|
txdata := &types.DynamicFeeTx{
|
||||||
ChainID: gspec.Config.ChainID,
|
ChainID: gspec.Config.ChainID,
|
||||||
Nonce: 0,
|
Nonce: uint64(i),
|
||||||
To: &config.DepositContractAddress,
|
To: &config.DepositContractAddress,
|
||||||
Gas: 500_000,
|
Gas: 500000,
|
||||||
GasFeeCap: newGwei(5),
|
GasFeeCap: newGwei(5),
|
||||||
GasTipCap: big.NewInt(2),
|
GasTipCap: big.NewInt(2),
|
||||||
})
|
AccessList: nil,
|
||||||
b.AddTx(depositTx)
|
Data: []byte{},
|
||||||
|
}
|
||||||
// create withdrawal request
|
tx := types.NewTx(txdata)
|
||||||
withdrawalTx := types.MustSignNewTx(key1, signer, &types.DynamicFeeTx{
|
tx, _ = types.SignTx(tx, signer, key)
|
||||||
ChainID: gspec.Config.ChainID,
|
b.AddTx(tx)
|
||||||
Nonce: 1,
|
}
|
||||||
To: ¶ms.WithdrawalQueueAddress,
|
|
||||||
Gas: 500_000,
|
|
||||||
GasFeeCap: newGwei(5),
|
|
||||||
GasTipCap: big.NewInt(2),
|
|
||||||
Value: newGwei(1),
|
|
||||||
Data: common.FromHex("b917cfdc0d25b72d55cf94db328e1629b7f4fde2c30cdacf873b664416f76a0c7f7cc50c9f72a3cb84be88144cde91250000000000000d80"),
|
|
||||||
})
|
|
||||||
b.AddTx(withdrawalTx)
|
|
||||||
|
|
||||||
// create consolidation request
|
|
||||||
consolidationTx := types.MustSignNewTx(key1, signer, &types.DynamicFeeTx{
|
|
||||||
ChainID: gspec.Config.ChainID,
|
|
||||||
Nonce: 2,
|
|
||||||
To: ¶ms.ConsolidationQueueAddress,
|
|
||||||
Gas: 500_000,
|
|
||||||
GasFeeCap: newGwei(5),
|
|
||||||
GasTipCap: big.NewInt(2),
|
|
||||||
Value: newGwei(1),
|
|
||||||
Data: common.FromHex("b917cfdc0d25b72d55cf94db328e1629b7f4fde2c30cdacf873b664416f76a0c7f7cc50c9f72a3cb84be88144cde9125b9812f7d0b1f2f969b52bbb2d316b0c2fa7c9dba85c428c5e6c27766bcc4b0c6e874702ff1eb1c7024b08524a9771601"),
|
|
||||||
})
|
|
||||||
b.AddTx(consolidationTx)
|
|
||||||
})
|
})
|
||||||
|
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{DisableStack: true}, os.Stderr).Hooks()}, nil)
|
||||||
// Check block has the correct requests hash.
|
|
||||||
rh := blocks[0].RequestsHash()
|
|
||||||
if rh == nil {
|
|
||||||
t.Fatal("block has nil requests hash")
|
|
||||||
}
|
|
||||||
expectedRequestsHash := common.HexToHash("0x06ffb72b9f0823510b128bca6cd4f96f59b745de6791e9fc350b596e7605101e")
|
|
||||||
if *rh != expectedRequestsHash {
|
|
||||||
t.Fatalf("block has wrong requestsHash %v, want %v", *rh, expectedRequestsHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert block to check validation.
|
|
||||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tester chain: %v", err)
|
t.Fatalf("failed to create tester chain: %v", err)
|
||||||
}
|
}
|
||||||
@@ -4231,4 +4285,32 @@ func TestPragueRequests(t *testing.T) {
|
|||||||
if n, err := chain.InsertChain(blocks); err != nil {
|
if n, err := chain.InsertChain(blocks); err != nil {
|
||||||
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
block := chain.GetBlockByNumber(1)
|
||||||
|
if len(block.Requests()) != 5 {
|
||||||
|
t.Fatalf("failed to retrieve deposits: have %d, want %d", len(block.Requests()), 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify each index is correct.
|
||||||
|
for want, req := range block.Requests() {
|
||||||
|
d, ok := req.Inner().(*types.Deposit)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("expected deposit object")
|
||||||
|
}
|
||||||
|
if got := int(d.PublicKey[0]); got != want {
|
||||||
|
t.Fatalf("invalid pubkey: have %d, want %d", got, want)
|
||||||
|
}
|
||||||
|
if got := int(d.WithdrawalCredentials[0]); got != want {
|
||||||
|
t.Fatalf("invalid withdrawal credentials: have %d, want %d", got, want)
|
||||||
|
}
|
||||||
|
if d.Amount != uint64(want) {
|
||||||
|
t.Fatalf("invalid amounbt: have %d, want %d", d.Amount, want)
|
||||||
|
}
|
||||||
|
if got := int(d.Signature[0]); got != want {
|
||||||
|
t.Fatalf("invalid signature: have %d, want %d", got, want)
|
||||||
|
}
|
||||||
|
if d.Index != uint64(want) {
|
||||||
|
t.Fatalf("invalid index: have %d, want %d", d.Index, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,19 +222,20 @@ func (c *ChainIndexer) eventLoop(currentHeader *types.Header, events chan ChainH
|
|||||||
errc <- nil
|
errc <- nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ev.Header.ParentHash != prevHash {
|
header := ev.Block.Header()
|
||||||
|
if header.ParentHash != prevHash {
|
||||||
// Reorg to the common ancestor if needed (might not exist in light sync mode, skip reorg then)
|
// Reorg to the common ancestor if needed (might not exist in light sync mode, skip reorg then)
|
||||||
// TODO(karalabe, zsfelfoldi): This seems a bit brittle, can we detect this case explicitly?
|
// TODO(karalabe, zsfelfoldi): This seems a bit brittle, can we detect this case explicitly?
|
||||||
|
|
||||||
if rawdb.ReadCanonicalHash(c.chainDb, prevHeader.Number.Uint64()) != prevHash {
|
if rawdb.ReadCanonicalHash(c.chainDb, prevHeader.Number.Uint64()) != prevHash {
|
||||||
if h := rawdb.FindCommonAncestor(c.chainDb, prevHeader, ev.Header); h != nil {
|
if h := rawdb.FindCommonAncestor(c.chainDb, prevHeader, header); h != nil {
|
||||||
c.newHead(h.Number.Uint64(), true)
|
c.newHead(h.Number.Uint64(), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.newHead(ev.Header.Number.Uint64(), false)
|
c.newHead(header.Number.Uint64(), false)
|
||||||
|
|
||||||
prevHeader, prevHash = ev.Header, ev.Header.Hash()
|
prevHeader, prevHash = header, header.Hash()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -346,34 +346,18 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
|||||||
gen(i, b)
|
gen(i, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
var requests [][]byte
|
var requests types.Requests
|
||||||
if config.IsPrague(b.header.Number, b.header.Time) {
|
if config.IsPrague(b.header.Number, b.header.Time) {
|
||||||
// EIP-6110 deposits
|
|
||||||
var blockLogs []*types.Log
|
|
||||||
for _, r := range b.receipts {
|
for _, r := range b.receipts {
|
||||||
blockLogs = append(blockLogs, r.Logs...)
|
d, err := ParseDepositLogs(r.Logs, config)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
|
||||||
|
}
|
||||||
|
requests = append(requests, d...)
|
||||||
}
|
}
|
||||||
depositRequests, err := ParseDepositLogs(blockLogs, config)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("failed to parse deposit log: %v", err))
|
|
||||||
}
|
|
||||||
requests = append(requests, depositRequests)
|
|
||||||
// create EVM for system calls
|
|
||||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
|
||||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, cm.config, vm.Config{})
|
|
||||||
// EIP-7002 withdrawals
|
|
||||||
withdrawalRequests := ProcessWithdrawalQueue(vmenv, statedb)
|
|
||||||
requests = append(requests, withdrawalRequests)
|
|
||||||
// EIP-7251 consolidations
|
|
||||||
consolidationRequests := ProcessConsolidationQueue(vmenv, statedb)
|
|
||||||
requests = append(requests, consolidationRequests)
|
|
||||||
}
|
|
||||||
if requests != nil {
|
|
||||||
reqHash := types.CalcRequestsHash(requests)
|
|
||||||
b.header.RequestsHash = &reqHash
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals}
|
body := types.Body{Transactions: b.txs, Uncles: b.uncles, Withdrawals: b.withdrawals, Requests: requests}
|
||||||
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
|
block, err := b.engine.FinalizeAndAssemble(cm, b.header, statedb, &body, b.receipts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -462,15 +446,16 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
|||||||
// Save pre state for proof generation
|
// Save pre state for proof generation
|
||||||
// preState := statedb.Copy()
|
// preState := statedb.Copy()
|
||||||
|
|
||||||
// Pre-execution system calls.
|
// TODO uncomment when the 2935 PR is merged
|
||||||
if config.IsPrague(b.header.Number, b.header.Time) {
|
// if config.IsPrague(b.header.Number, b.header.Time) {
|
||||||
// EIP-2935
|
// if !config.IsPrague(b.parent.Number(), b.parent.Time()) {
|
||||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
// Transition case: insert all 256 ancestors
|
||||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, cm.config, vm.Config{})
|
// InsertBlockHashHistoryAtEip2935Fork(statedb, b.header.Number.Uint64()-1, b.header.ParentHash, chainreader)
|
||||||
ProcessParentBlockHash(b.header.ParentHash, vmenv, statedb)
|
// } else {
|
||||||
}
|
// ProcessParentBlockHash(statedb, b.header.Number.Uint64()-1, b.header.ParentHash)
|
||||||
|
// }
|
||||||
// Execute any user modifications to the block.
|
// }
|
||||||
|
// Execute any user modifications to the block
|
||||||
if gen != nil {
|
if gen != nil {
|
||||||
gen(i, b)
|
gen(i, b)
|
||||||
}
|
}
|
||||||
@@ -484,7 +469,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write state changes to DB.
|
// Write state changes to db
|
||||||
root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number))
|
root, err := statedb.Commit(b.header.Number.Uint64(), config.IsEIP158(b.header.Number))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("state write error: %v", err))
|
panic(fmt.Sprintf("state write error: %v", err))
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ func TestGeneratePOSChain(t *testing.T) {
|
|||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
config.TerminalTotalDifficultyPassed = true
|
||||||
config.TerminalTotalDifficulty = common.Big0
|
config.TerminalTotalDifficulty = common.Big0
|
||||||
config.ShanghaiTime = u64(0)
|
config.ShanghaiTime = u64(0)
|
||||||
config.CancunTime = u64(0)
|
config.CancunTime = u64(0)
|
||||||
|
|||||||
@@ -17,19 +17,27 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewTxsEvent is posted when a batch of transactions enter the transaction pool.
|
// NewTxsEvent is posted when a batch of transactions enter the transaction pool.
|
||||||
type NewTxsEvent struct{ Txs []*types.Transaction }
|
type NewTxsEvent struct{ Txs []*types.Transaction }
|
||||||
|
|
||||||
|
// NewMinedBlockEvent is posted when a block has been imported.
|
||||||
|
type NewMinedBlockEvent struct{ Block *types.Block }
|
||||||
|
|
||||||
// RemovedLogsEvent is posted when a reorg happens
|
// RemovedLogsEvent is posted when a reorg happens
|
||||||
type RemovedLogsEvent struct{ Logs []*types.Log }
|
type RemovedLogsEvent struct{ Logs []*types.Log }
|
||||||
|
|
||||||
type ChainEvent struct {
|
type ChainEvent struct {
|
||||||
Header *types.Header
|
Block *types.Block
|
||||||
|
Hash common.Hash
|
||||||
|
Logs []*types.Log
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChainHeadEvent struct {
|
type ChainSideEvent struct {
|
||||||
Header *types.Header
|
Block *types.Block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChainHeadEvent struct{ Block *types.Block }
|
||||||
|
|||||||
@@ -378,25 +378,26 @@ func TestTimeBasedForkInGenesis(t *testing.T) {
|
|||||||
forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes()))
|
forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes()))
|
||||||
config = func(shanghai, cancun uint64) *params.ChainConfig {
|
config = func(shanghai, cancun uint64) *params.ChainConfig {
|
||||||
return ¶ms.ChainConfig{
|
return ¶ms.ChainConfig{
|
||||||
ChainID: big.NewInt(1337),
|
ChainID: big.NewInt(1337),
|
||||||
HomesteadBlock: big.NewInt(0),
|
HomesteadBlock: big.NewInt(0),
|
||||||
DAOForkBlock: nil,
|
DAOForkBlock: nil,
|
||||||
DAOForkSupport: true,
|
DAOForkSupport: true,
|
||||||
EIP150Block: big.NewInt(0),
|
EIP150Block: big.NewInt(0),
|
||||||
EIP155Block: big.NewInt(0),
|
EIP155Block: big.NewInt(0),
|
||||||
EIP158Block: big.NewInt(0),
|
EIP158Block: big.NewInt(0),
|
||||||
ByzantiumBlock: big.NewInt(0),
|
ByzantiumBlock: big.NewInt(0),
|
||||||
ConstantinopleBlock: big.NewInt(0),
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
PetersburgBlock: big.NewInt(0),
|
PetersburgBlock: big.NewInt(0),
|
||||||
IstanbulBlock: big.NewInt(0),
|
IstanbulBlock: big.NewInt(0),
|
||||||
MuirGlacierBlock: big.NewInt(0),
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
BerlinBlock: big.NewInt(0),
|
BerlinBlock: big.NewInt(0),
|
||||||
LondonBlock: big.NewInt(0),
|
LondonBlock: big.NewInt(0),
|
||||||
TerminalTotalDifficulty: big.NewInt(0),
|
TerminalTotalDifficulty: big.NewInt(0),
|
||||||
MergeNetsplitBlock: big.NewInt(0),
|
TerminalTotalDifficultyPassed: true,
|
||||||
ShanghaiTime: &shanghai,
|
MergeNetsplitBlock: big.NewInt(0),
|
||||||
CancunTime: &cancun,
|
ShanghaiTime: &shanghai,
|
||||||
Ethash: new(params.EthashConfig),
|
CancunTime: &cancun,
|
||||||
|
Ethash: new(params.EthashConfig),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -449,6 +449,7 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
|
|||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
withdrawals []*types.Withdrawal
|
withdrawals []*types.Withdrawal
|
||||||
|
requests types.Requests
|
||||||
)
|
)
|
||||||
if conf := g.Config; conf != nil {
|
if conf := g.Config; conf != nil {
|
||||||
num := big.NewInt(int64(g.Number))
|
num := big.NewInt(int64(g.Number))
|
||||||
@@ -472,12 +473,11 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if conf.IsPrague(num, g.Timestamp) {
|
if conf.IsPrague(num, g.Timestamp) {
|
||||||
emptyRequests := [][]byte{{0x00}, {0x01}, {0x02}}
|
head.RequestsHash = &types.EmptyRequestsHash
|
||||||
rhash := types.CalcRequestsHash(emptyRequests)
|
requests = make(types.Requests, 0)
|
||||||
head.RequestsHash = &rhash
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
|
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals, Requests: requests}, nil, trie.NewStackTrie(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit writes the block and state of a genesis specification to the database.
|
// Commit writes the block and state of a genesis specification to the database.
|
||||||
@@ -588,11 +588,10 @@ func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
|
|||||||
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
|
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
|
||||||
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
|
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
|
||||||
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
|
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
|
||||||
// Pre-deploy system contracts
|
// Pre-deploy EIP-4788 system contract
|
||||||
params.BeaconRootsAddress: {Nonce: 1, Code: params.BeaconRootsCode, Balance: common.Big0},
|
params.BeaconRootsAddress: {Nonce: 1, Code: params.BeaconRootsCode, Balance: common.Big0},
|
||||||
params.HistoryStorageAddress: {Nonce: 1, Code: params.HistoryStorageCode, Balance: common.Big0},
|
// Pre-deploy EIP-2935 history contract.
|
||||||
params.WithdrawalQueueAddress: {Nonce: 1, Code: params.WithdrawalQueueCode, Balance: common.Big0},
|
params.HistoryStorageAddress: {Nonce: 1, Code: params.HistoryStorageCode},
|
||||||
params.ConsolidationQueueAddress: {Nonce: 1, Code: params.ConsolidationQueueCode, Balance: common.Big0},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if faucet != nil {
|
if faucet != nil {
|
||||||
|
|||||||
@@ -257,30 +257,31 @@ func newDbConfig(scheme string) *triedb.Config {
|
|||||||
func TestVerkleGenesisCommit(t *testing.T) {
|
func TestVerkleGenesisCommit(t *testing.T) {
|
||||||
var verkleTime uint64 = 0
|
var verkleTime uint64 = 0
|
||||||
verkleConfig := ¶ms.ChainConfig{
|
verkleConfig := ¶ms.ChainConfig{
|
||||||
ChainID: big.NewInt(1),
|
ChainID: big.NewInt(1),
|
||||||
HomesteadBlock: big.NewInt(0),
|
HomesteadBlock: big.NewInt(0),
|
||||||
DAOForkBlock: nil,
|
DAOForkBlock: nil,
|
||||||
DAOForkSupport: false,
|
DAOForkSupport: false,
|
||||||
EIP150Block: big.NewInt(0),
|
EIP150Block: big.NewInt(0),
|
||||||
EIP155Block: big.NewInt(0),
|
EIP155Block: big.NewInt(0),
|
||||||
EIP158Block: big.NewInt(0),
|
EIP158Block: big.NewInt(0),
|
||||||
ByzantiumBlock: big.NewInt(0),
|
ByzantiumBlock: big.NewInt(0),
|
||||||
ConstantinopleBlock: big.NewInt(0),
|
ConstantinopleBlock: big.NewInt(0),
|
||||||
PetersburgBlock: big.NewInt(0),
|
PetersburgBlock: big.NewInt(0),
|
||||||
IstanbulBlock: big.NewInt(0),
|
IstanbulBlock: big.NewInt(0),
|
||||||
MuirGlacierBlock: big.NewInt(0),
|
MuirGlacierBlock: big.NewInt(0),
|
||||||
BerlinBlock: big.NewInt(0),
|
BerlinBlock: big.NewInt(0),
|
||||||
LondonBlock: big.NewInt(0),
|
LondonBlock: big.NewInt(0),
|
||||||
ArrowGlacierBlock: big.NewInt(0),
|
ArrowGlacierBlock: big.NewInt(0),
|
||||||
GrayGlacierBlock: big.NewInt(0),
|
GrayGlacierBlock: big.NewInt(0),
|
||||||
MergeNetsplitBlock: nil,
|
MergeNetsplitBlock: nil,
|
||||||
ShanghaiTime: &verkleTime,
|
ShanghaiTime: &verkleTime,
|
||||||
CancunTime: &verkleTime,
|
CancunTime: &verkleTime,
|
||||||
PragueTime: &verkleTime,
|
PragueTime: &verkleTime,
|
||||||
VerkleTime: &verkleTime,
|
VerkleTime: &verkleTime,
|
||||||
TerminalTotalDifficulty: big.NewInt(0),
|
TerminalTotalDifficulty: big.NewInt(0),
|
||||||
Ethash: nil,
|
TerminalTotalDifficultyPassed: true,
|
||||||
Clique: nil,
|
Ethash: nil,
|
||||||
|
Clique: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
genesis := &Genesis{
|
genesis := &Genesis{
|
||||||
|
|||||||
@@ -388,10 +388,10 @@ func TestBlockReceiptStorage(t *testing.T) {
|
|||||||
// Insert the receipt slice into the database and check presence
|
// Insert the receipt slice into the database and check presence
|
||||||
WriteReceipts(db, hash, 0, receipts)
|
WriteReceipts(db, hash, 0, receipts)
|
||||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) == 0 {
|
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) == 0 {
|
||||||
t.Fatal("no receipts returned")
|
t.Fatalf("no receipts returned")
|
||||||
} else {
|
} else {
|
||||||
if err := checkReceiptsRLP(rs, receipts); err != nil {
|
if err := checkReceiptsRLP(rs, receipts); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed)
|
// Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed)
|
||||||
@@ -401,7 +401,7 @@ func TestBlockReceiptStorage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// Ensure that receipts without metadata can be returned without the block body too
|
// Ensure that receipts without metadata can be returned without the block body too
|
||||||
if err := checkReceiptsRLP(ReadRawReceipts(db, hash, 0), receipts); err != nil {
|
if err := checkReceiptsRLP(ReadRawReceipts(db, hash, 0), receipts); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
// Sanity check that body alone without the receipt is a full purge
|
// Sanity check that body alone without the receipt is a full purge
|
||||||
WriteBody(db, hash, 0, body)
|
WriteBody(db, hash, 0, body)
|
||||||
|
|||||||
@@ -35,17 +35,17 @@ var newTestHasher = blocktest.NewHasher
|
|||||||
func TestLookupStorage(t *testing.T) {
|
func TestLookupStorage(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
writeTxLookupEntriesByBlock func(ethdb.KeyValueWriter, *types.Block)
|
writeTxLookupEntriesByBlock func(ethdb.Writer, *types.Block)
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"DatabaseV6",
|
"DatabaseV6",
|
||||||
func(db ethdb.KeyValueWriter, block *types.Block) {
|
func(db ethdb.Writer, block *types.Block) {
|
||||||
WriteTxLookupEntriesByBlock(db, block)
|
WriteTxLookupEntriesByBlock(db, block)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DatabaseV4-V5",
|
"DatabaseV4-V5",
|
||||||
func(db ethdb.KeyValueWriter, block *types.Block) {
|
func(db ethdb.Writer, block *types.Block) {
|
||||||
for _, tx := range block.Transactions() {
|
for _, tx := range block.Transactions() {
|
||||||
db.Put(txLookupKey(tx.Hash()), block.Hash().Bytes())
|
db.Put(txLookupKey(tx.Hash()), block.Hash().Bytes())
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ func TestLookupStorage(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"DatabaseV3",
|
"DatabaseV3",
|
||||||
func(db ethdb.KeyValueWriter, block *types.Block) {
|
func(db ethdb.Writer, block *types.Block) {
|
||||||
for index, tx := range block.Transactions() {
|
for index, tx := range block.Transactions() {
|
||||||
entry := LegacyTxLookupEntry{
|
entry := LegacyTxLookupEntry{
|
||||||
BlockHash: block.Hash(),
|
BlockHash: block.Hash(),
|
||||||
|
|||||||
@@ -302,10 +302,6 @@ func ParseStateScheme(provided string, disk ethdb.Database) (string, error) {
|
|||||||
log.Info("State scheme set to already existing", "scheme", stored)
|
log.Info("State scheme set to already existing", "scheme", stored)
|
||||||
return stored, nil // reuse scheme of persistent scheme
|
return stored, nil // reuse scheme of persistent scheme
|
||||||
}
|
}
|
||||||
// If state scheme is specified, ensure it's valid.
|
|
||||||
if provided != HashScheme && provided != PathScheme {
|
|
||||||
return "", fmt.Errorf("invalid state scheme %s", provided)
|
|
||||||
}
|
|
||||||
// If state scheme is specified, ensure it's compatible with
|
// If state scheme is specified, ensure it's compatible with
|
||||||
// persistent state.
|
// persistent state.
|
||||||
if stored == "" || provided == stored {
|
if stored == "" || provided == stored {
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb/leveldb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
"github.com/ethereum/go-ethereum/ethdb/memorydb"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb/pebble"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/olekukonko/tablewriter"
|
||||||
)
|
)
|
||||||
@@ -297,9 +299,37 @@ func NewMemoryDatabase() ethdb.Database {
|
|||||||
return NewDatabase(memorydb.New())
|
return NewDatabase(memorydb.New())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewMemoryDatabaseWithCap creates an ephemeral in-memory key-value database
|
||||||
|
// with an initial starting capacity, but without a freezer moving immutable
|
||||||
|
// chain segments into cold storage.
|
||||||
|
func NewMemoryDatabaseWithCap(size int) ethdb.Database {
|
||||||
|
return NewDatabase(memorydb.NewWithCap(size))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLevelDBDatabase creates a persistent key-value database without a freezer
|
||||||
|
// moving immutable chain segments into cold storage.
|
||||||
|
func NewLevelDBDatabase(file string, cache int, handles int, namespace string, readonly bool) (ethdb.Database, error) {
|
||||||
|
db, err := leveldb.New(file, cache, handles, namespace, readonly)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
log.Info("Using LevelDB as the backing database")
|
||||||
|
return NewDatabase(db), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPebbleDBDatabase creates a persistent key-value database without a freezer
|
||||||
|
// moving immutable chain segments into cold storage.
|
||||||
|
func NewPebbleDBDatabase(file string, cache int, handles int, namespace string, readonly, ephemeral bool) (ethdb.Database, error) {
|
||||||
|
db, err := pebble.New(file, cache, handles, namespace, readonly, ephemeral)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewDatabase(db), nil
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DBPebble = "pebble"
|
dbPebble = "pebble"
|
||||||
DBLeveldb = "leveldb"
|
dbLeveldb = "leveldb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PreexistingDatabase checks the given data directory whether a database is already
|
// PreexistingDatabase checks the given data directory whether a database is already
|
||||||
@@ -313,9 +343,75 @@ func PreexistingDatabase(path string) string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err) // only possible if the pattern is malformed
|
panic(err) // only possible if the pattern is malformed
|
||||||
}
|
}
|
||||||
return DBPebble
|
return dbPebble
|
||||||
}
|
}
|
||||||
return DBLeveldb
|
return dbLeveldb
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenOptions contains the options to apply when opening a database.
|
||||||
|
// OBS: If AncientsDirectory is empty, it indicates that no freezer is to be used.
|
||||||
|
type OpenOptions struct {
|
||||||
|
Type string // "leveldb" | "pebble"
|
||||||
|
Directory string // the datadir
|
||||||
|
AncientsDirectory string // the ancients-dir
|
||||||
|
Namespace string // the namespace for database relevant metrics
|
||||||
|
Cache int // the capacity(in megabytes) of the data caching
|
||||||
|
Handles int // number of files to be open simultaneously
|
||||||
|
ReadOnly bool
|
||||||
|
// Ephemeral means that filesystem sync operations should be avoided: data integrity in the face of
|
||||||
|
// a crash is not important. This option should typically be used in tests.
|
||||||
|
Ephemeral bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// openKeyValueDatabase opens a disk-based key-value database, e.g. leveldb or pebble.
|
||||||
|
//
|
||||||
|
// type == null type != null
|
||||||
|
// +----------------------------------------
|
||||||
|
// db is non-existent | pebble default | specified type
|
||||||
|
// db is existent | from db | specified type (if compatible)
|
||||||
|
func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
|
||||||
|
// Reject any unsupported database type
|
||||||
|
if len(o.Type) != 0 && o.Type != dbLeveldb && o.Type != dbPebble {
|
||||||
|
return nil, fmt.Errorf("unknown db.engine %v", o.Type)
|
||||||
|
}
|
||||||
|
// Retrieve any pre-existing database's type and use that or the requested one
|
||||||
|
// as long as there's no conflict between the two types
|
||||||
|
existingDb := PreexistingDatabase(o.Directory)
|
||||||
|
if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb {
|
||||||
|
return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb)
|
||||||
|
}
|
||||||
|
if o.Type == dbPebble || existingDb == dbPebble {
|
||||||
|
log.Info("Using pebble as the backing database")
|
||||||
|
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral)
|
||||||
|
}
|
||||||
|
if o.Type == dbLeveldb || existingDb == dbLeveldb {
|
||||||
|
log.Info("Using leveldb as the backing database")
|
||||||
|
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||||
|
}
|
||||||
|
// No pre-existing database, no user-requested one either. Default to Pebble.
|
||||||
|
log.Info("Defaulting to pebble as the backing database")
|
||||||
|
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly, o.Ephemeral)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open opens both a disk-based key-value database such as leveldb or pebble, but also
|
||||||
|
// integrates it with a freezer database -- if the AncientDir option has been
|
||||||
|
// set on the provided OpenOptions.
|
||||||
|
// The passed o.AncientDir indicates the path of root ancient directory where
|
||||||
|
// the chain freezer can be opened.
|
||||||
|
func Open(o OpenOptions) (ethdb.Database, error) {
|
||||||
|
kvdb, err := openKeyValueDatabase(o)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(o.AncientsDirectory) == 0 {
|
||||||
|
return kvdb, nil
|
||||||
|
}
|
||||||
|
frdb, err := NewDatabaseWithFreezer(kvdb, o.AncientsDirectory, o.Namespace, o.ReadOnly)
|
||||||
|
if err != nil {
|
||||||
|
kvdb.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return frdb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type counter uint64
|
type counter uint64
|
||||||
|
|||||||
@@ -58,9 +58,8 @@ const freezerTableSize = 2 * 1000 * 1000 * 1000
|
|||||||
// - The append-only nature ensures that disk writes are minimized.
|
// - The append-only nature ensures that disk writes are minimized.
|
||||||
// - The in-order data ensures that disk reads are always optimized.
|
// - The in-order data ensures that disk reads are always optimized.
|
||||||
type Freezer struct {
|
type Freezer struct {
|
||||||
datadir string
|
frozen atomic.Uint64 // Number of items already frozen
|
||||||
frozen atomic.Uint64 // Number of items already frozen
|
tail atomic.Uint64 // Number of the first stored item in the freezer
|
||||||
tail atomic.Uint64 // Number of the first stored item in the freezer
|
|
||||||
|
|
||||||
// This lock synchronizes writers and the truncate operation, as well as
|
// This lock synchronizes writers and the truncate operation, as well as
|
||||||
// the "atomic" (batched) read operations.
|
// the "atomic" (batched) read operations.
|
||||||
@@ -110,7 +109,6 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui
|
|||||||
}
|
}
|
||||||
// Open all the supported data tables
|
// Open all the supported data tables
|
||||||
freezer := &Freezer{
|
freezer := &Freezer{
|
||||||
datadir: datadir,
|
|
||||||
readonly: readonly,
|
readonly: readonly,
|
||||||
tables: make(map[string]*freezerTable),
|
tables: make(map[string]*freezerTable),
|
||||||
instanceLock: lock,
|
instanceLock: lock,
|
||||||
@@ -174,11 +172,6 @@ func (f *Freezer) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AncientDatadir returns the path of the ancient store.
|
|
||||||
func (f *Freezer) AncientDatadir() (string, error) {
|
|
||||||
return f.datadir, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasAncient returns an indicator whether the specified ancient data exists
|
// HasAncient returns an indicator whether the specified ancient data exists
|
||||||
// in the freezer.
|
// in the freezer.
|
||||||
func (f *Freezer) HasAncient(kind string, number uint64) (bool, error) {
|
func (f *Freezer) HasAncient(kind string, number uint64) (bool, error) {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ package rawdb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/golang/snappy"
|
"github.com/golang/snappy"
|
||||||
)
|
)
|
||||||
@@ -180,10 +180,10 @@ func (batch *freezerTableBatch) maybeCommit() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// commit writes the batched items to the backing freezerTable. Note index
|
// commit writes the batched items to the backing freezerTable.
|
||||||
// file isn't fsync'd after the file write, the recent write can be lost
|
|
||||||
// after the power failure.
|
|
||||||
func (batch *freezerTableBatch) commit() error {
|
func (batch *freezerTableBatch) commit() error {
|
||||||
|
// Write data. The head file is fsync'd after write to ensure the
|
||||||
|
// data is truly transferred to disk.
|
||||||
_, err := batch.t.head.Write(batch.dataBuffer)
|
_, err := batch.t.head.Write(batch.dataBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -194,10 +194,15 @@ func (batch *freezerTableBatch) commit() error {
|
|||||||
dataSize := int64(len(batch.dataBuffer))
|
dataSize := int64(len(batch.dataBuffer))
|
||||||
batch.dataBuffer = batch.dataBuffer[:0]
|
batch.dataBuffer = batch.dataBuffer[:0]
|
||||||
|
|
||||||
|
// Write indices. The index file is fsync'd after write to ensure the
|
||||||
|
// data indexes are truly transferred to disk.
|
||||||
_, err = batch.t.index.Write(batch.indexBuffer)
|
_, err = batch.t.index.Write(batch.indexBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := batch.t.index.Sync(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
indexSize := int64(len(batch.indexBuffer))
|
indexSize := int64(len(batch.indexBuffer))
|
||||||
batch.indexBuffer = batch.indexBuffer[:0]
|
batch.indexBuffer = batch.indexBuffer[:0]
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ package rawdb
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
@@ -419,9 +419,3 @@ func (f *MemoryFreezer) Reset() error {
|
|||||||
f.items, f.tail = 0, 0
|
f.items, f.tail = 0, 0
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AncientDatadir returns the path of the ancient store.
|
|
||||||
// Since the memory freezer is ephemeral, an empty string is returned.
|
|
||||||
func (f *MemoryFreezer) AncientDatadir() (string, error) {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user