mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-03 06:42:57 +00:00
Compare commits
3 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
737ffd1bf0 | ||
|
|
41714b4975 | ||
|
|
d818a9af7b |
662 changed files with 24403 additions and 54524 deletions
|
|
@ -122,27 +122,6 @@ jobs:
|
|||
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
|
||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
||||
|
||||
keeper:
|
||||
name: Keeper Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.24
|
||||
cache: false
|
||||
|
||||
- name: Install cross toolchain
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
|
||||
|
||||
- name: Build (amd64)
|
||||
run: |
|
||||
go run build/ci.go keeper -dlgo
|
||||
|
||||
windows:
|
||||
name: Windows Build
|
||||
runs-on: "win-11"
|
||||
|
|
@ -166,24 +145,6 @@ jobs:
|
|||
env:
|
||||
GETH_MINGW: 'C:\msys64\mingw64'
|
||||
|
||||
- name: "Create/upload archive (amd64)"
|
||||
shell: cmd
|
||||
run: |
|
||||
go run build/ci.go archive -arch amd64 -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
||||
env:
|
||||
WINDOWS_SIGNING_KEY: ${{ secrets.WINDOWS_SIGNING_KEY }}
|
||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
||||
|
||||
- name: "Create/upload NSIS installer (amd64)"
|
||||
shell: cmd
|
||||
run: |
|
||||
set "PATH=C:\Program Files (x86)\NSIS;%PATH%"
|
||||
go run build/ci.go nsis -arch amd64 -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
||||
del /Q build\bin\*
|
||||
env:
|
||||
WINDOWS_SIGNING_KEY: ${{ secrets.WINDOWS_SIGNING_KEY }}
|
||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
||||
|
||||
- name: "Build (386)"
|
||||
shell: cmd
|
||||
run: |
|
||||
|
|
@ -192,24 +153,6 @@ jobs:
|
|||
env:
|
||||
GETH_MINGW: 'C:\msys64\mingw32'
|
||||
|
||||
- name: "Create/upload archive (386)"
|
||||
shell: cmd
|
||||
run: |
|
||||
go run build/ci.go archive -arch 386 -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
||||
env:
|
||||
WINDOWS_SIGNING_KEY: ${{ secrets.WINDOWS_SIGNING_KEY }}
|
||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
||||
|
||||
- name: "Create/upload NSIS installer (386)"
|
||||
shell: cmd
|
||||
run: |
|
||||
set "PATH=C:\Program Files (x86)\NSIS;%PATH%"
|
||||
go run build/ci.go nsis -arch 386 -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
||||
del /Q build\bin\*
|
||||
env:
|
||||
WINDOWS_SIGNING_KEY: ${{ secrets.WINDOWS_SIGNING_KEY }}
|
||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
||||
|
||||
docker:
|
||||
name: Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
|
@ -10,7 +10,6 @@ beacon/merkle/ @zsfelfoldi
|
|||
beacon/types/ @zsfelfoldi @fjl
|
||||
beacon/params/ @zsfelfoldi @fjl
|
||||
cmd/evm/ @MariusVanDerWijden @lightclient
|
||||
cmd/keeper/ @gballet
|
||||
core/state/ @rjl493456442
|
||||
crypto/ @gballet @jwasinger @fjl
|
||||
core/ @rjl493456442
|
||||
|
|
|
|||
29
.github/workflows/freebsd.yml
vendored
29
.github/workflows/freebsd.yml
vendored
|
|
@ -1,29 +0,0 @@
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
- freebsd-github-action
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: FreeBSD-build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Test in FreeBSD
|
||||
id: test
|
||||
uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
release: "15.0"
|
||||
usesh: true
|
||||
prepare: |
|
||||
pkg install -y go
|
||||
run: |
|
||||
freebsd-version
|
||||
uname -a
|
||||
go version
|
||||
go run ./build/ci.go test -p 8
|
||||
82
.github/workflows/go.yml
vendored
82
.github/workflows/go.yml
vendored
|
|
@ -34,47 +34,6 @@ jobs:
|
|||
go run build/ci.go check_generate
|
||||
go run build/ci.go check_baddeps
|
||||
|
||||
keeper:
|
||||
name: Keeper Builds
|
||||
needs: test
|
||||
runs-on: [self-hosted-ghr, size-l-x64]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.25'
|
||||
cache: false
|
||||
|
||||
- name: Build
|
||||
run: go run build/ci.go keeper
|
||||
|
||||
test-32bit:
|
||||
name: "32bit tests"
|
||||
needs: test
|
||||
runs-on: [self-hosted-ghr, size-l-x64]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.25'
|
||||
cache: false
|
||||
|
||||
- name: Install cross toolchain
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
|
||||
|
||||
- name: Build
|
||||
run: go run build/ci.go test -arch 386 -short -p 8
|
||||
|
||||
test:
|
||||
name: Test
|
||||
needs: lint
|
||||
|
|
@ -97,44 +56,3 @@ jobs:
|
|||
|
||||
- name: Run tests
|
||||
run: go run build/ci.go test -p 8
|
||||
|
||||
windows:
|
||||
name: Windows ${{ matrix.arch }}
|
||||
needs: lint
|
||||
runs-on: [self-hosted, windows, x64]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
mingw: 'C:\msys64\mingw64'
|
||||
test: true
|
||||
- arch: '386'
|
||||
mingw: 'C:\msys64\mingw32'
|
||||
test: false
|
||||
env:
|
||||
GETH_MINGW: ${{ matrix.mingw }}
|
||||
GETH_CC: ${{ matrix.mingw }}\bin\gcc.exe
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.25'
|
||||
cache: false
|
||||
|
||||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
set PATH=%GETH_MINGW%\bin;%PATH%
|
||||
go run build/ci.go install -arch ${{ matrix.arch }} -cc %GETH_CC%
|
||||
|
||||
- name: Run tests
|
||||
if: matrix.test
|
||||
shell: cmd
|
||||
run: |
|
||||
set PATH=%GETH_MINGW%\bin;%PATH%
|
||||
go run build/ci.go test -arch ${{ matrix.arch }} -cc %GETH_CC% -short -p 8
|
||||
|
|
|
|||
60
.github/workflows/validate_pr.yml
vendored
60
.github/workflows/validate_pr.yml
vendored
|
|
@ -8,54 +8,10 @@ jobs:
|
|||
validate-pr:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check for Spam PR
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const prTitle = context.payload.pull_request.title;
|
||||
const spamRegex = /^(feat|chore|fix)(\(.*\))?\s*:/i;
|
||||
|
||||
if (spamRegex.test(prTitle)) {
|
||||
// Leave a comment explaining why
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
body: `## PR Closed as Spam
|
||||
|
||||
This PR was automatically closed because the title format \`feat:\`, \`fix:\`, or \`chore:\` is commonly associated with spam contributions.
|
||||
|
||||
If this is a legitimate contribution, please:
|
||||
1. Review our contribution guidelines
|
||||
2. Use the correct PR title format: \`directory, ...: description\`
|
||||
3. Open a new PR with the proper title format
|
||||
|
||||
Thank you for your understanding.`
|
||||
});
|
||||
|
||||
// Close the PR
|
||||
await github.rest.pulls.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.payload.pull_request.number,
|
||||
state: 'closed'
|
||||
});
|
||||
|
||||
core.setFailed('PR closed as spam due to suspicious title format');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ PR passed spam check');
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check PR Title Format
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const prTitle = context.payload.pull_request.title;
|
||||
const titleRegex = /^([\w\s,{}/.]+): .+/;
|
||||
|
||||
|
|
@ -64,20 +20,4 @@ jobs:
|
|||
return;
|
||||
}
|
||||
|
||||
const match = prTitle.match(titleRegex);
|
||||
const dirPart = match[1];
|
||||
const directories = dirPart.split(',').map(d => d.trim());
|
||||
const missingDirs = [];
|
||||
for (const dir of directories) {
|
||||
const fullPath = path.join(process.env.GITHUB_WORKSPACE, dir);
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
missingDirs.push(dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingDirs.length > 0) {
|
||||
core.setFailed(`The following directories in the PR title do not exist: ${missingDirs.join(', ')}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ PR title format is valid');
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -56,4 +56,3 @@ cmd/evm/evm
|
|||
cmd/geth/geth
|
||||
cmd/rlpdump/rlpdump
|
||||
cmd/workload/workload
|
||||
cmd/keeper/keeper
|
||||
|
|
|
|||
102
AGENTS.md
102
AGENTS.md
|
|
@ -1,102 +0,0 @@
|
|||
# AGENTS
|
||||
|
||||
## Guidelines
|
||||
|
||||
- **Keep changes minimal and focused.** Only modify code directly related to the task at hand. Do not refactor unrelated code, rename existing variables or functions for style, or bundle unrelated fixes into the same commit or PR.
|
||||
- **Do not add, remove, or update dependencies** unless the task explicitly requires it.
|
||||
|
||||
## Pre-Commit Checklist
|
||||
|
||||
Before every commit, run **all** of the following checks and ensure they pass:
|
||||
|
||||
### 1. Formatting
|
||||
|
||||
Before committing, always run `gofmt` and `goimports` on all modified files:
|
||||
|
||||
```sh
|
||||
gofmt -w <modified files>
|
||||
goimports -w <modified files>
|
||||
```
|
||||
|
||||
### 2. Build All Commands
|
||||
|
||||
Verify that all tools compile successfully:
|
||||
|
||||
```sh
|
||||
make all
|
||||
```
|
||||
|
||||
This builds all executables under `cmd/`, including `keeper` which has special build requirements.
|
||||
|
||||
### 3. Tests
|
||||
|
||||
While iterating during development, use `-short` for faster feedback:
|
||||
|
||||
```sh
|
||||
go run ./build/ci.go test -short
|
||||
```
|
||||
|
||||
Before committing, run the full test suite **without** `-short` to ensure all tests pass, including the Ethereum execution-spec tests and all state/block test permutations:
|
||||
|
||||
```sh
|
||||
go run ./build/ci.go test
|
||||
```
|
||||
|
||||
### 4. Linting
|
||||
|
||||
```sh
|
||||
go run ./build/ci.go lint
|
||||
```
|
||||
|
||||
This runs additional style checks. Fix any issues before committing.
|
||||
|
||||
### 5. Generated Code
|
||||
|
||||
```sh
|
||||
go run ./build/ci.go check_generate
|
||||
```
|
||||
|
||||
Ensures that all generated files (e.g., `gen_*.go`) are up to date. If this fails, first install the required code generators by running `make devtools`, then run the appropriate `go generate` commands and include the updated files in your commit.
|
||||
|
||||
### 6. Dependency Hygiene
|
||||
|
||||
```sh
|
||||
go run ./build/ci.go check_baddeps
|
||||
```
|
||||
|
||||
Verifies that no forbidden dependencies have been introduced.
|
||||
|
||||
## What to include in commits
|
||||
|
||||
Do not commit binaries, whether they are produced by the main build or byproducts of investigations.
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
Commit messages must be prefixed with the package(s) they modify, followed by a short lowercase description:
|
||||
|
||||
```
|
||||
<package(s)>: description
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `core/vm: fix stack overflow in PUSH instruction`
|
||||
- `eth, rpc: make trace configs optional`
|
||||
- `cmd/geth: add new flag for sync mode`
|
||||
|
||||
Use comma-separated package names when multiple areas are affected. Keep the description concise.
|
||||
|
||||
## Pull Request Title Format
|
||||
|
||||
PR titles follow the same convention as commit messages:
|
||||
|
||||
```
|
||||
<list of modified paths>: description
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `core/vm: fix stack overflow in PUSH instruction`
|
||||
- `core, eth: add arena allocator support`
|
||||
- `cmd/geth, internal/ethapi: refactor transaction args`
|
||||
- `trie/archiver: streaming subtree archival to fix OOM`
|
||||
|
||||
Use the top-level package paths, comma-separated if multiple areas are affected. Only mention the directories with functional changes, interface changes that trickle all over the codebase should not generate an exhaustive list. The description should be a short, lowercase summary of the change.
|
||||
|
|
@ -4,7 +4,7 @@ ARG VERSION=""
|
|||
ARG BUILDNUM=""
|
||||
|
||||
# Build Geth in a stock Go builder container
|
||||
FROM golang:1.26-alpine AS builder
|
||||
FROM golang:1.24-alpine AS builder
|
||||
|
||||
RUN apk add --no-cache gcc musl-dev linux-headers git
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ ARG VERSION=""
|
|||
ARG BUILDNUM=""
|
||||
|
||||
# Build Geth in a stock Go builder container
|
||||
FROM golang:1.26-alpine AS builder
|
||||
FROM golang:1.24-alpine AS builder
|
||||
|
||||
RUN apk add --no-cache gcc musl-dev linux-headers git
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ Audit reports are published in the `docs` folder: https://github.com/ethereum/go
|
|||
|
||||
To find out how to disclose a vulnerability in Ethereum visit [https://bounty.ethereum.org](https://bounty.ethereum.org) or email bounty@ethereum.org. Please read the [disclosure page](https://github.com/ethereum/go-ethereum/security/advisories?state=published) for more information about publicly disclosed security vulnerabilities.
|
||||
|
||||
Use the built-in `geth version-check` feature to check whether the software is affected by any known vulnerability. This command will fetch the latest [`vulnerabilities.json`](https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json) file which contains known security vulnerabilities concerning `geth`, and cross-check the data against its own version number.
|
||||
|
||||
The following key may be used to communicate sensitive information to developers.
|
||||
|
||||
|
|
|
|||
|
|
@ -183,11 +183,8 @@ var (
|
|||
// Solidity: {{.Original.String}}
|
||||
func ({{ decapitalise $contract.Type}} *{{$contract.Type}}) Unpack{{.Normalized.Name}}Event(log *types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
|
||||
event := "{{.Original.Name}}"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != {{ decapitalise $contract.Type}}.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != {{ decapitalise $contract.Type}}.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new({{$contract.Type}}{{.Normalized.Name}})
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
|
|
@ -360,11 +360,8 @@ func (CrowdsaleFundTransfer) ContractEventName() string {
|
|||
// Solidity: event FundTransfer(address backer, uint256 amount, bool isContribution)
|
||||
func (crowdsale *Crowdsale) UnpackFundTransferEvent(log *types.Log) (*CrowdsaleFundTransfer, error) {
|
||||
event := "FundTransfer"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != crowdsale.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != crowdsale.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(CrowdsaleFundTransfer)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
35
accounts/abi/abigen/testdata/v2/dao.go.txt
vendored
35
accounts/abi/abigen/testdata/v2/dao.go.txt
vendored
|
|
@ -606,11 +606,8 @@ func (DAOChangeOfRules) ContractEventName() string {
|
|||
// Solidity: event ChangeOfRules(uint256 minimumQuorum, uint256 debatingPeriodInMinutes, int256 majorityMargin)
|
||||
func (dAO *DAO) UnpackChangeOfRulesEvent(log *types.Log) (*DAOChangeOfRules, error) {
|
||||
event := "ChangeOfRules"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != dAO.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != dAO.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(DAOChangeOfRules)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -651,11 +648,8 @@ func (DAOMembershipChanged) ContractEventName() string {
|
|||
// Solidity: event MembershipChanged(address member, bool isMember)
|
||||
func (dAO *DAO) UnpackMembershipChangedEvent(log *types.Log) (*DAOMembershipChanged, error) {
|
||||
event := "MembershipChanged"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != dAO.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != dAO.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(DAOMembershipChanged)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -698,11 +692,8 @@ func (DAOProposalAdded) ContractEventName() string {
|
|||
// Solidity: event ProposalAdded(uint256 proposalID, address recipient, uint256 amount, string description)
|
||||
func (dAO *DAO) UnpackProposalAddedEvent(log *types.Log) (*DAOProposalAdded, error) {
|
||||
event := "ProposalAdded"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != dAO.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != dAO.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(DAOProposalAdded)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -745,11 +736,8 @@ func (DAOProposalTallied) ContractEventName() string {
|
|||
// Solidity: event ProposalTallied(uint256 proposalID, int256 result, uint256 quorum, bool active)
|
||||
func (dAO *DAO) UnpackProposalTalliedEvent(log *types.Log) (*DAOProposalTallied, error) {
|
||||
event := "ProposalTallied"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != dAO.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != dAO.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(DAOProposalTallied)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -792,11 +780,8 @@ func (DAOVoted) ContractEventName() string {
|
|||
// Solidity: event Voted(uint256 proposalID, bool position, address voter, string justification)
|
||||
func (dAO *DAO) UnpackVotedEvent(log *types.Log) (*DAOVoted, error) {
|
||||
event := "Voted"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != dAO.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != dAO.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(DAOVoted)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
|
|
@ -72,11 +72,8 @@ func (EventCheckerDynamic) ContractEventName() string {
|
|||
// Solidity: event dynamic(string indexed idxStr, bytes indexed idxDat, string str, bytes dat)
|
||||
func (eventChecker *EventChecker) UnpackDynamicEvent(log *types.Log) (*EventCheckerDynamic, error) {
|
||||
event := "dynamic"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(EventCheckerDynamic)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -115,11 +112,8 @@ func (EventCheckerEmpty) ContractEventName() string {
|
|||
// Solidity: event empty()
|
||||
func (eventChecker *EventChecker) UnpackEmptyEvent(log *types.Log) (*EventCheckerEmpty, error) {
|
||||
event := "empty"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(EventCheckerEmpty)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -160,11 +154,8 @@ func (EventCheckerIndexed) ContractEventName() string {
|
|||
// Solidity: event indexed(address indexed addr, int256 indexed num)
|
||||
func (eventChecker *EventChecker) UnpackIndexedEvent(log *types.Log) (*EventCheckerIndexed, error) {
|
||||
event := "indexed"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(EventCheckerIndexed)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -205,11 +196,8 @@ func (EventCheckerMixed) ContractEventName() string {
|
|||
// Solidity: event mixed(address indexed addr, int256 num)
|
||||
func (eventChecker *EventChecker) UnpackMixedEvent(log *types.Log) (*EventCheckerMixed, error) {
|
||||
event := "mixed"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(EventCheckerMixed)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -250,11 +238,8 @@ func (EventCheckerUnnamed) ContractEventName() string {
|
|||
// Solidity: event unnamed(uint256 indexed arg0, uint256 indexed arg1)
|
||||
func (eventChecker *EventChecker) UnpackUnnamedEvent(log *types.Log) (*EventCheckerUnnamed, error) {
|
||||
event := "unnamed"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != eventChecker.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(EventCheckerUnnamed)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
|
|
@ -134,11 +134,8 @@ func (NameConflictLog) ContractEventName() string {
|
|||
// Solidity: event log(int256 msg, int256 _msg)
|
||||
func (nameConflict *NameConflict) UnpackLogEvent(log *types.Log) (*NameConflictLog, error) {
|
||||
event := "log"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != nameConflict.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != nameConflict.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(NameConflictLog)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
|
|
@ -136,11 +136,8 @@ func (NumericMethodNameE1TestEvent) ContractEventName() string {
|
|||
// Solidity: event _1TestEvent(address _param)
|
||||
func (numericMethodName *NumericMethodName) UnpackE1TestEventEvent(log *types.Log) (*NumericMethodNameE1TestEvent, error) {
|
||||
event := "_1TestEvent"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != numericMethodName.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != numericMethodName.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(NumericMethodNameE1TestEvent)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
14
accounts/abi/abigen/testdata/v2/overload.go.txt
vendored
14
accounts/abi/abigen/testdata/v2/overload.go.txt
vendored
|
|
@ -114,11 +114,8 @@ func (OverloadBar) ContractEventName() string {
|
|||
// Solidity: event bar(uint256 i)
|
||||
func (overload *Overload) UnpackBarEvent(log *types.Log) (*OverloadBar, error) {
|
||||
event := "bar"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != overload.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != overload.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(OverloadBar)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -159,11 +156,8 @@ func (OverloadBar0) ContractEventName() string {
|
|||
// Solidity: event bar(uint256 i, uint256 j)
|
||||
func (overload *Overload) UnpackBar0Event(log *types.Log) (*OverloadBar0, error) {
|
||||
event := "bar0"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != overload.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != overload.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(OverloadBar0)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
7
accounts/abi/abigen/testdata/v2/token.go.txt
vendored
7
accounts/abi/abigen/testdata/v2/token.go.txt
vendored
|
|
@ -386,11 +386,8 @@ func (TokenTransfer) ContractEventName() string {
|
|||
// Solidity: event Transfer(address indexed from, address indexed to, uint256 value)
|
||||
func (token *Token) UnpackTransferEvent(log *types.Log) (*TokenTransfer, error) {
|
||||
event := "Transfer"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != token.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != token.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(TokenTransfer)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
14
accounts/abi/abigen/testdata/v2/tuple.go.txt
vendored
14
accounts/abi/abigen/testdata/v2/tuple.go.txt
vendored
|
|
@ -193,11 +193,8 @@ func (TupleTupleEvent) ContractEventName() string {
|
|||
// Solidity: event TupleEvent((uint256,uint256[],(uint256,uint256)[]) a, (uint256,uint256)[2][] b, (uint256,uint256)[][2] c, (uint256,uint256[],(uint256,uint256)[])[] d, uint256[] e)
|
||||
func (tuple *Tuple) UnpackTupleEventEvent(log *types.Log) (*TupleTupleEvent, error) {
|
||||
event := "TupleEvent"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != tuple.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != tuple.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(TupleTupleEvent)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -237,11 +234,8 @@ func (TupleTupleEvent2) ContractEventName() string {
|
|||
// Solidity: event TupleEvent2((uint8,uint8)[] arg0)
|
||||
func (tuple *Tuple) UnpackTupleEvent2Event(log *types.Log) (*TupleTupleEvent2, error) {
|
||||
event := "TupleEvent2"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != tuple.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != tuple.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(TupleTupleEvent2)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ import (
|
|||
const basefeeWiggleMultiplier = 2
|
||||
|
||||
var (
|
||||
ErrNoEventSignature = errors.New("no event signature")
|
||||
ErrEventSignatureMismatch = errors.New("event signature mismatch")
|
||||
errNoEventSignature = errors.New("no event signature")
|
||||
errEventSignatureMismatch = errors.New("event signature mismatch")
|
||||
)
|
||||
|
||||
// SignerFn is a signer function callback when a contract requires a method to
|
||||
|
|
@ -536,10 +536,10 @@ func (c *BoundContract) WatchLogs(opts *WatchOpts, name string, query ...[]any)
|
|||
func (c *BoundContract) UnpackLog(out any, event string, log types.Log) error {
|
||||
// Anonymous events are not supported.
|
||||
if len(log.Topics) == 0 {
|
||||
return ErrNoEventSignature
|
||||
return errNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != c.abi.Events[event].ID {
|
||||
return ErrEventSignatureMismatch
|
||||
return errEventSignatureMismatch
|
||||
}
|
||||
if len(log.Data) > 0 {
|
||||
if err := c.abi.UnpackIntoInterface(out, event, log.Data); err != nil {
|
||||
|
|
@ -559,10 +559,10 @@ func (c *BoundContract) UnpackLog(out any, event string, log types.Log) error {
|
|||
func (c *BoundContract) UnpackLogIntoMap(out map[string]any, event string, log types.Log) error {
|
||||
// Anonymous events are not supported.
|
||||
if len(log.Topics) == 0 {
|
||||
return ErrNoEventSignature
|
||||
return errNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != c.abi.Events[event].ID {
|
||||
return ErrEventSignatureMismatch
|
||||
return errEventSignatureMismatch
|
||||
}
|
||||
if len(log.Data) > 0 {
|
||||
if err := c.abi.UnpackIntoMap(out, event, log.Data); err != nil {
|
||||
|
|
|
|||
|
|
@ -158,10 +158,10 @@ func testLinkCase(tcInput linkTestCaseInput) error {
|
|||
overrideAddrs = make(map[rune]common.Address)
|
||||
)
|
||||
// generate deterministic addresses for the override set.
|
||||
rng := rand.New(rand.NewSource(42))
|
||||
rand.Seed(42)
|
||||
for contract := range tcInput.overrides {
|
||||
var addr common.Address
|
||||
rng.Read(addr[:])
|
||||
rand.Read(addr[:])
|
||||
overrideAddrs[contract] = addr
|
||||
overridesAddrs[addr] = struct{}{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,11 +276,8 @@ func (DBInsert) ContractEventName() string {
|
|||
// Solidity: event Insert(uint256 key, uint256 value, uint256 length)
|
||||
func (dB *DB) UnpackInsertEvent(log *types.Log) (*DBInsert, error) {
|
||||
event := "Insert"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != dB.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != dB.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(DBInsert)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -321,11 +318,8 @@ func (DBKeyedInsert) ContractEventName() string {
|
|||
// Solidity: event KeyedInsert(uint256 indexed key, uint256 value)
|
||||
func (dB *DB) UnpackKeyedInsertEvent(log *types.Log) (*DBKeyedInsert, error) {
|
||||
event := "KeyedInsert"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != dB.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != dB.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(DBKeyedInsert)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
|
|
@ -115,11 +115,8 @@ func (CBasic1) ContractEventName() string {
|
|||
// Solidity: event basic1(uint256 indexed id, uint256 data)
|
||||
func (c *C) UnpackBasic1Event(log *types.Log) (*CBasic1, error) {
|
||||
event := "basic1"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != c.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != c.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(CBasic1)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
@ -160,11 +157,8 @@ func (CBasic2) ContractEventName() string {
|
|||
// Solidity: event basic2(bool indexed flag, uint256 data)
|
||||
func (c *C) UnpackBasic2Event(log *types.Log) (*CBasic2, error) {
|
||||
event := "basic2"
|
||||
if len(log.Topics) == 0 {
|
||||
return nil, bind.ErrNoEventSignature
|
||||
}
|
||||
if log.Topics[0] != c.abi.Events[event].ID {
|
||||
return nil, bind.ErrEventSignatureMismatch
|
||||
if len(log.Topics) == 0 || log.Topics[0] != c.abi.Events[event].ID {
|
||||
return nil, errors.New("event signature mismatch")
|
||||
}
|
||||
out := new(CBasic2)
|
||||
if len(log.Data) > 0 {
|
||||
|
|
|
|||
|
|
@ -379,16 +379,16 @@ func TestEventUnpackEmptyTopics(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatal("expected error when unpacking event with empty topics, got nil")
|
||||
}
|
||||
if err != bind.ErrNoEventSignature {
|
||||
t.Fatalf("expected 'no event signature' error, got: %v", err)
|
||||
if err.Error() != "event signature mismatch" {
|
||||
t.Fatalf("expected 'event signature mismatch' error, got: %v", err)
|
||||
}
|
||||
|
||||
_, err = c.UnpackBasic2Event(log)
|
||||
if err == nil {
|
||||
t.Fatal("expected error when unpacking event with empty topics, got nil")
|
||||
}
|
||||
if err != bind.ErrNoEventSignature {
|
||||
t.Fatalf("expected 'no event signature' error, got: %v", err)
|
||||
if err.Error() != "event signature mismatch" {
|
||||
t.Fatalf("expected 'event signature mismatch' error, got: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,9 +144,10 @@ func TestWaitDeployedCornerCases(t *testing.T) {
|
|||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
want := errors.New("context canceled")
|
||||
_, err := bind.WaitDeployed(ctx, backend.Client(), tx.Hash())
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
t.Errorf("error mismatch: want %v, got %v", context.Canceled, err)
|
||||
if err == nil || errors.Is(want, err) {
|
||||
t.Errorf("error mismatch: want %v, got %v", want, err)
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ import (
|
|||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto/keccak"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// Account represents an Ethereum account located at a specific location defined
|
||||
|
|
@ -196,7 +196,7 @@ func TextHash(data []byte) []byte {
|
|||
// This gives context to the signed message and prevents signing of transactions.
|
||||
func TextAndHash(data []byte) ([]byte, string) {
|
||||
msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), data)
|
||||
hasher := keccak.NewLegacyKeccak256()
|
||||
hasher := sha3.NewLegacyKeccak256()
|
||||
hasher.Write([]byte(msg))
|
||||
return hasher.Sum(nil), msg
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,27 +68,18 @@ func waitWatcherStart(ks *KeyStore) bool {
|
|||
|
||||
func waitForAccounts(wantAccounts []accounts.Account, ks *KeyStore) error {
|
||||
var list []accounts.Account
|
||||
haveAccounts := false
|
||||
haveChange := false
|
||||
for t0 := time.Now(); time.Since(t0) < 5*time.Second; time.Sleep(100 * time.Millisecond) {
|
||||
if !haveAccounts {
|
||||
list = ks.Accounts()
|
||||
haveAccounts = reflect.DeepEqual(list, wantAccounts)
|
||||
}
|
||||
if !haveChange {
|
||||
list = ks.Accounts()
|
||||
if reflect.DeepEqual(list, wantAccounts) {
|
||||
// ks should have also received change notifications
|
||||
select {
|
||||
case <-ks.changes:
|
||||
haveChange = true
|
||||
default:
|
||||
return errors.New("wasn't notified of new accounts")
|
||||
}
|
||||
}
|
||||
if haveAccounts && haveChange {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if haveAccounts {
|
||||
return errors.New("wasn't notified of new accounts")
|
||||
}
|
||||
return fmt.Errorf("\ngot %v\nwant %v", list, wantAccounts)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -418,7 +418,6 @@ func (ks *KeyStore) Export(a accounts.Account, passphrase, newPassphrase string)
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer zeroKey(key.PrivateKey)
|
||||
var N, P int
|
||||
if store, ok := ks.storage.(*keyStorePassphrase); ok {
|
||||
N, P = store.scryptN, store.scryptP
|
||||
|
|
@ -478,7 +477,6 @@ func (ks *KeyStore) Update(a accounts.Account, passphrase, newPassphrase string)
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zeroKey(key.PrivateKey)
|
||||
return ks.storage.StoreKey(a.URL.Path, key, newPassphrase)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,9 +81,6 @@ func decryptPreSaleKey(fileContent []byte, password string) (key *Key, err error
|
|||
*/
|
||||
passBytes := []byte(password)
|
||||
derivedKey := pbkdf2.Key(passBytes, passBytes, 2000, 16, sha256.New)
|
||||
if len(cipherText)%aes.BlockSize != 0 {
|
||||
return nil, errors.New("ciphertext must be a multiple of block size")
|
||||
}
|
||||
plainText, err := aesCBCDecrypt(derivedKey, cipherText, iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
// 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/>.
|
||||
|
||||
//go:build (darwin && !ios && cgo) || freebsd || linux || netbsd || solaris
|
||||
// +build darwin,!ios,cgo freebsd linux netbsd solaris
|
||||
//go:build (darwin && !ios && cgo) || freebsd || (linux && !arm64) || netbsd || solaris
|
||||
// +build darwin,!ios,cgo freebsd linux,!arm64 netbsd solaris
|
||||
|
||||
package keystore
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
// 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/>.
|
||||
|
||||
//go:build (darwin && !cgo) || ios || windows || (!darwin && !freebsd && !linux && !netbsd && !solaris)
|
||||
// +build darwin,!cgo ios windows !darwin,!freebsd,!linux,!netbsd,!solaris
|
||||
//go:build (darwin && !cgo) || ios || (linux && arm64) || windows || (!darwin && !freebsd && !linux && !netbsd && !solaris)
|
||||
// +build darwin,!cgo ios linux,arm64 windows !darwin,!freebsd,!linux,!netbsd,!solaris
|
||||
|
||||
// This is the fallback implementation of directory watching.
|
||||
// It is used on unsupported platforms.
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ func (hub *Hub) readPairings() error {
|
|||
}
|
||||
|
||||
func (hub *Hub) writePairings() error {
|
||||
pairingFile, err := os.OpenFile(filepath.Join(hub.datadir, "smartcards.json"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
||||
pairingFile, err := os.OpenFile(filepath.Join(hub.datadir, "smartcards.json"), os.O_RDWR|os.O_CREATE, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -129,8 +129,11 @@ func (hub *Hub) writePairings() error {
|
|||
return err
|
||||
}
|
||||
|
||||
_, err = pairingFile.Write(pairingData)
|
||||
return err
|
||||
if _, err := pairingFile.Write(pairingData); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hub *Hub) pairing(wallet *Wallet) *smartcardPairing {
|
||||
|
|
|
|||
|
|
@ -300,10 +300,6 @@ func (s *SecureChannelSession) decryptAPDU(data []byte) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if len(data) == 0 || len(data)%aes.BlockSize != 0 {
|
||||
return nil, fmt.Errorf("invalid ciphertext length: %d", len(data))
|
||||
}
|
||||
|
||||
ret := make([]byte, len(data))
|
||||
|
||||
crypter := cipher.NewCBCDecrypter(a, s.iv)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/hid"
|
||||
"github.com/karalabe/hid"
|
||||
)
|
||||
|
||||
// LedgerScheme is the protocol scheme prefixing account and wallet URLs.
|
||||
|
|
@ -43,14 +43,6 @@ const refreshCycle = time.Second
|
|||
// trashing.
|
||||
const refreshThrottling = 500 * time.Millisecond
|
||||
|
||||
const (
|
||||
// deviceUsagePage identifies Ledger devices by HID usage page (0xffa0) on Windows and macOS.
|
||||
// See: https://github.com/LedgerHQ/ledger-live/blob/05a2980e838955a11a1418da638ef8ac3df4fb74/libs/ledgerjs/packages/hw-transport-node-hid-noevents/src/TransportNodeHid.ts
|
||||
deviceUsagePage = 0xffa0
|
||||
// deviceInterface identifies Ledger devices by USB interface number (0) on Linux.
|
||||
deviceInterface = 0
|
||||
)
|
||||
|
||||
// Hub is a accounts.Backend that can find and handle generic USB hardware wallets.
|
||||
type Hub struct {
|
||||
scheme string // Protocol scheme prefixing account and wallet URLs.
|
||||
|
|
@ -90,7 +82,6 @@ func NewLedgerHub() (*Hub, error) {
|
|||
0x0005, /* Ledger Nano S Plus */
|
||||
0x0006, /* Ledger Nano FTS */
|
||||
0x0007, /* Ledger Flex */
|
||||
0x0008, /* Ledger Nano Gen5 */
|
||||
|
||||
0x0000, /* WebUSB Ledger Blue */
|
||||
0x1000, /* WebUSB Ledger Nano S */
|
||||
|
|
@ -98,8 +89,7 @@ func NewLedgerHub() (*Hub, error) {
|
|||
0x5000, /* WebUSB Ledger Nano S Plus */
|
||||
0x6000, /* WebUSB Ledger Nano FTS */
|
||||
0x7000, /* WebUSB Ledger Flex */
|
||||
0x8000, /* WebUSB Ledger Nano Gen5 */
|
||||
}, deviceUsagePage, deviceInterface, newLedgerDriver)
|
||||
}, 0xffa0, 0, newLedgerDriver)
|
||||
}
|
||||
|
||||
// NewTrezorHubWithHID creates a new hardware wallet manager for Trezor devices.
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ func (w *ledgerDriver) SignTypedMessage(path accounts.DerivationPath, domainHash
|
|||
return nil, accounts.ErrWalletClosed
|
||||
}
|
||||
// Ensure the wallet is capable of signing the given transaction
|
||||
if w.version[0] < 1 || (w.version[0] == 1 && w.version[1] < 5) {
|
||||
if w.version[0] < 1 && w.version[1] < 5 {
|
||||
//lint:ignore ST1005 brand name displayed on the console
|
||||
return nil, fmt.Errorf("Ledger version >= 1.5.0 required for EIP-712 signing (found version v%d.%d.%d)", w.version[0], w.version[1], w.version[2])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/hid"
|
||||
"github.com/karalabe/hid"
|
||||
)
|
||||
|
||||
// Maximum time between wallet health checks to detect USB unplugs.
|
||||
|
|
@ -632,7 +632,7 @@ func (w *wallet) SignTx(account accounts.Account, tx *types.Transaction, chainID
|
|||
// data is not supported for Ledger wallets, so this method will always return
|
||||
// an error.
|
||||
func (w *wallet) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) {
|
||||
return w.SignText(account, text)
|
||||
return w.SignText(account, accounts.TextHash(text))
|
||||
}
|
||||
|
||||
// SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given
|
||||
|
|
|
|||
|
|
@ -36,4 +36,4 @@ for:
|
|||
- go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
||||
- go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
||||
test_script:
|
||||
- go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -short
|
||||
- go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -short -skip-spectests
|
||||
|
|
|
|||
|
|
@ -87,10 +87,6 @@ func (ec *engineClient) updateLoop(headCh <-chan types.ChainHeadEvent) {
|
|||
if status, err := ec.callForkchoiceUpdated(forkName, event); err == nil {
|
||||
log.Info("Successful ForkchoiceUpdated", "head", event.Block.Hash(), "status", status)
|
||||
} else {
|
||||
if err.Error() == "beacon syncer reorging" {
|
||||
log.Debug("Failed ForkchoiceUpdated", "head", event.Block.Hash(), "error", err)
|
||||
continue // ignore beacon syncer reorging errors, this error can occur if the blsync is skipping a block
|
||||
}
|
||||
log.Error("Failed ForkchoiceUpdated", "head", event.Block.Hash(), "error", err)
|
||||
}
|
||||
}
|
||||
|
|
@ -105,16 +101,7 @@ func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent)
|
|||
params = []any{execData}
|
||||
)
|
||||
switch fork {
|
||||
case "altair", "bellatrix":
|
||||
method = "engine_newPayloadV1"
|
||||
case "capella":
|
||||
method = "engine_newPayloadV2"
|
||||
case "deneb":
|
||||
method = "engine_newPayloadV3"
|
||||
parentBeaconRoot := event.BeaconHead.ParentRoot
|
||||
blobHashes := collectBlobHashes(event.Block)
|
||||
params = append(params, blobHashes, parentBeaconRoot)
|
||||
default: // electra, fulu and above
|
||||
case "electra":
|
||||
method = "engine_newPayloadV4"
|
||||
parentBeaconRoot := event.BeaconHead.ParentRoot
|
||||
blobHashes := collectBlobHashes(event.Block)
|
||||
|
|
@ -123,6 +110,15 @@ func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent)
|
|||
hexRequests[i] = hexutil.Bytes(event.ExecRequests[i])
|
||||
}
|
||||
params = append(params, blobHashes, parentBeaconRoot, hexRequests)
|
||||
case "deneb":
|
||||
method = "engine_newPayloadV3"
|
||||
parentBeaconRoot := event.BeaconHead.ParentRoot
|
||||
blobHashes := collectBlobHashes(event.Block)
|
||||
params = append(params, blobHashes, parentBeaconRoot)
|
||||
case "capella":
|
||||
method = "engine_newPayloadV2"
|
||||
default:
|
||||
method = "engine_newPayloadV1"
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ec.rootCtx, time.Second*5)
|
||||
|
|
@ -149,12 +145,12 @@ func (ec *engineClient) callForkchoiceUpdated(fork string, event types.ChainHead
|
|||
|
||||
var method string
|
||||
switch fork {
|
||||
case "altair", "bellatrix":
|
||||
method = "engine_forkchoiceUpdatedV1"
|
||||
case "deneb", "electra":
|
||||
method = "engine_forkchoiceUpdatedV3"
|
||||
case "capella":
|
||||
method = "engine_forkchoiceUpdatedV2"
|
||||
default: // deneb, electra, fulu and above
|
||||
method = "engine_forkchoiceUpdatedV3"
|
||||
default:
|
||||
method = "engine_forkchoiceUpdatedV1"
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ec.rootCtx, time.Second*5)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
|
|||
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *hexutil.Uint64 `json:"slotNumber"`
|
||||
}
|
||||
var enc PayloadAttributes
|
||||
enc.Timestamp = hexutil.Uint64(p.Timestamp)
|
||||
|
|
@ -29,7 +28,6 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
|
|||
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
|
||||
enc.Withdrawals = p.Withdrawals
|
||||
enc.BeaconRoot = p.BeaconRoot
|
||||
enc.SlotNumber = (*hexutil.Uint64)(p.SlotNumber)
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +39,6 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
|
|||
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *hexutil.Uint64 `json:"slotNumber"`
|
||||
}
|
||||
var dec PayloadAttributes
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -65,8 +62,5 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
|
|||
if dec.BeaconRoot != nil {
|
||||
p.BeaconRoot = dec.BeaconRoot
|
||||
}
|
||||
if dec.SlotNumber != nil {
|
||||
p.SlotNumber = (*uint64)(dec.SlotNumber)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,24 +17,24 @@ var _ = (*executableDataMarshaling)(nil)
|
|||
// MarshalJSON marshals as JSON.
|
||||
func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
||||
type ExecutableData struct {
|
||||
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
|
||||
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
|
||||
StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
|
||||
ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"`
|
||||
LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"`
|
||||
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
||||
Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"`
|
||||
GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
|
||||
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
||||
Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"`
|
||||
ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"`
|
||||
BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
|
||||
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
|
||||
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||
SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"`
|
||||
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
|
||||
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
|
||||
StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
|
||||
ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"`
|
||||
LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"`
|
||||
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
||||
Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"`
|
||||
GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
|
||||
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
||||
Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"`
|
||||
ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"`
|
||||
BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
|
||||
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
|
||||
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||
}
|
||||
var enc ExecutableData
|
||||
enc.ParentHash = e.ParentHash
|
||||
|
|
@ -59,31 +59,31 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
|||
enc.Withdrawals = e.Withdrawals
|
||||
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
||||
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
||||
enc.SlotNumber = (*hexutil.Uint64)(e.SlotNumber)
|
||||
enc.ExecutionWitness = e.ExecutionWitness
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
||||
type ExecutableData struct {
|
||||
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
|
||||
FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"`
|
||||
StateRoot *common.Hash `json:"stateRoot" gencodec:"required"`
|
||||
ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"`
|
||||
LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"`
|
||||
Random *common.Hash `json:"prevRandao" gencodec:"required"`
|
||||
Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"`
|
||||
GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
|
||||
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
||||
Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
|
||||
ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"`
|
||||
BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
|
||||
BlockHash *common.Hash `json:"blockHash" gencodec:"required"`
|
||||
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||
SlotNumber *hexutil.Uint64 `json:"slotNumber,omitempty"`
|
||||
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
|
||||
FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"`
|
||||
StateRoot *common.Hash `json:"stateRoot" gencodec:"required"`
|
||||
ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"`
|
||||
LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"`
|
||||
Random *common.Hash `json:"prevRandao" gencodec:"required"`
|
||||
Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"`
|
||||
GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
|
||||
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
|
||||
Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
|
||||
ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"`
|
||||
BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
|
||||
BlockHash *common.Hash `json:"blockHash" gencodec:"required"`
|
||||
Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||
}
|
||||
var dec ExecutableData
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -157,8 +157,8 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
|||
if dec.ExcessBlobGas != nil {
|
||||
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
||||
}
|
||||
if dec.SlotNumber != nil {
|
||||
e.SlotNumber = (*uint64)(dec.SlotNumber)
|
||||
if dec.ExecutionWitness != nil {
|
||||
e.ExecutionWitness = dec.ExecutionWitness
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,13 +50,6 @@ var (
|
|||
// ExecutionPayloadV3 has the syntax of ExecutionPayloadV2 and appends the new
|
||||
// fields: blobGasUsed and excessBlobGas.
|
||||
PayloadV3 PayloadVersion = 0x3
|
||||
|
||||
// PayloadV4 is the identifier of ExecutionPayloadV4 introduced in amsterdam fork.
|
||||
//
|
||||
// https://github.com/ethereum/execution-apis/blob/main/src/engine/amsterdam.md#executionpayloadv4
|
||||
// ExecutionPayloadV4 has the syntax of ExecutionPayloadV3 and appends the new
|
||||
// field slotNumber.
|
||||
PayloadV4 PayloadVersion = 0x4
|
||||
)
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
|
||||
|
|
@ -69,37 +62,35 @@ type PayloadAttributes struct {
|
|||
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *uint64 `json:"slotNumber"`
|
||||
}
|
||||
|
||||
// JSON type overrides for PayloadAttributes.
|
||||
type payloadAttributesMarshaling struct {
|
||||
Timestamp hexutil.Uint64
|
||||
SlotNumber *hexutil.Uint64
|
||||
Timestamp hexutil.Uint64
|
||||
}
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go
|
||||
|
||||
// ExecutableData is the data necessary to execute an EL payload.
|
||||
type ExecutableData struct {
|
||||
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
|
||||
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
|
||||
StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
|
||||
ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"`
|
||||
LogsBloom []byte `json:"logsBloom" gencodec:"required"`
|
||||
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
||||
Number uint64 `json:"blockNumber" gencodec:"required"`
|
||||
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
|
||||
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
|
||||
Timestamp uint64 `json:"timestamp" gencodec:"required"`
|
||||
ExtraData []byte `json:"extraData" gencodec:"required"`
|
||||
BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"`
|
||||
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
|
||||
Transactions [][]byte `json:"transactions" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
||||
SlotNumber *uint64 `json:"slotNumber,omitempty"`
|
||||
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
|
||||
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
|
||||
StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
|
||||
ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"`
|
||||
LogsBloom []byte `json:"logsBloom" gencodec:"required"`
|
||||
Random common.Hash `json:"prevRandao" gencodec:"required"`
|
||||
Number uint64 `json:"blockNumber" gencodec:"required"`
|
||||
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
|
||||
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
|
||||
Timestamp uint64 `json:"timestamp" gencodec:"required"`
|
||||
ExtraData []byte `json:"extraData" gencodec:"required"`
|
||||
BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"`
|
||||
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
|
||||
Transactions [][]byte `json:"transactions" gencodec:"required"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||
}
|
||||
|
||||
// JSON type overrides for executableData.
|
||||
|
|
@ -114,7 +105,6 @@ type executableDataMarshaling struct {
|
|||
Transactions []hexutil.Bytes
|
||||
BlobGasUsed *hexutil.Uint64
|
||||
ExcessBlobGas *hexutil.Uint64
|
||||
SlotNumber *hexutil.Uint64
|
||||
}
|
||||
|
||||
// StatelessPayloadStatusV1 is the result of a stateless payload execution.
|
||||
|
|
@ -224,7 +214,7 @@ func encodeTransactions(txs []*types.Transaction) [][]byte {
|
|||
return enc
|
||||
}
|
||||
|
||||
func DecodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
|
||||
func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
|
||||
var txs = make([]*types.Transaction, len(enc))
|
||||
for i, encTx := range enc {
|
||||
var tx types.Transaction
|
||||
|
|
@ -262,7 +252,7 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
|||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -324,10 +314,10 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
|||
BlobGasUsed: data.BlobGasUsed,
|
||||
ParentBeaconRoot: beaconRoot,
|
||||
RequestsHash: requestsHash,
|
||||
SlotNumber: data.SlotNumber,
|
||||
}
|
||||
return types.NewBlockWithHeader(header).
|
||||
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}),
|
||||
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}).
|
||||
WithWitness(data.ExecutionWitness),
|
||||
nil
|
||||
}
|
||||
|
||||
|
|
@ -335,24 +325,24 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
|||
// 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 {
|
||||
data := &ExecutableData{
|
||||
BlockHash: block.Hash(),
|
||||
ParentHash: block.ParentHash(),
|
||||
FeeRecipient: block.Coinbase(),
|
||||
StateRoot: block.Root(),
|
||||
Number: block.NumberU64(),
|
||||
GasLimit: block.GasLimit(),
|
||||
GasUsed: block.GasUsed(),
|
||||
BaseFeePerGas: block.BaseFee(),
|
||||
Timestamp: block.Time(),
|
||||
ReceiptsRoot: block.ReceiptHash(),
|
||||
LogsBloom: block.Bloom().Bytes(),
|
||||
Transactions: encodeTransactions(block.Transactions()),
|
||||
Random: block.MixDigest(),
|
||||
ExtraData: block.Extra(),
|
||||
Withdrawals: block.Withdrawals(),
|
||||
BlobGasUsed: block.BlobGasUsed(),
|
||||
ExcessBlobGas: block.ExcessBlobGas(),
|
||||
SlotNumber: block.SlotNumber(),
|
||||
BlockHash: block.Hash(),
|
||||
ParentHash: block.ParentHash(),
|
||||
FeeRecipient: block.Coinbase(),
|
||||
StateRoot: block.Root(),
|
||||
Number: block.NumberU64(),
|
||||
GasLimit: block.GasLimit(),
|
||||
GasUsed: block.GasUsed(),
|
||||
BaseFeePerGas: block.BaseFee(),
|
||||
Timestamp: block.Time(),
|
||||
ReceiptsRoot: block.ReceiptHash(),
|
||||
LogsBloom: block.Bloom().Bytes(),
|
||||
Transactions: encodeTransactions(block.Transactions()),
|
||||
Random: block.MixDigest(),
|
||||
ExtraData: block.Extra(),
|
||||
Withdrawals: block.Withdrawals(),
|
||||
BlobGasUsed: block.BlobGasUsed(),
|
||||
ExcessBlobGas: block.ExcessBlobGas(),
|
||||
ExecutionWitness: block.ExecutionWitness(),
|
||||
}
|
||||
|
||||
// Add blobs.
|
||||
|
|
|
|||
|
|
@ -69,10 +69,7 @@ func newCanonicalStore[T any](db ethdb.Iteratee, keyPrefix []byte) (*canonicalSt
|
|||
|
||||
// databaseKey returns the database key belonging to the given period.
|
||||
func (cs *canonicalStore[T]) databaseKey(period uint64) []byte {
|
||||
key := make([]byte, len(cs.keyPrefix)+8)
|
||||
copy(key, cs.keyPrefix)
|
||||
binary.BigEndian.PutUint64(key[len(cs.keyPrefix):], period)
|
||||
return key
|
||||
return binary.BigEndian.AppendUint64(append([]byte{}, cs.keyPrefix...), period)
|
||||
}
|
||||
|
||||
// add adds the given item to the database. It also ensures that the range remains
|
||||
|
|
|
|||
|
|
@ -438,11 +438,14 @@ func (s *serverWithLimits) fail(desc string) {
|
|||
// failLocked calculates the dynamic failure delay and applies it.
|
||||
func (s *serverWithLimits) failLocked(desc string) {
|
||||
log.Debug("Server error", "description", desc)
|
||||
s.failureDelay *= 2
|
||||
now := s.clock.Now()
|
||||
if now > s.failureDelayEnd {
|
||||
s.failureDelay *= math.Pow(2, -float64(now-s.failureDelayEnd)/float64(maxFailureDelay))
|
||||
}
|
||||
s.failureDelay = max(min(s.failureDelay*2, float64(maxFailureDelay)), float64(minFailureDelay))
|
||||
if s.failureDelay < float64(minFailureDelay) {
|
||||
s.failureDelay = float64(minFailureDelay)
|
||||
}
|
||||
s.failureDelayEnd = now + mclock.AbsTime(s.failureDelay)
|
||||
s.delay(time.Duration(s.failureDelay))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ func (s *HeadSync) Process(requester request.Requester, events []request.Event)
|
|||
delete(s.serverHeads, event.Server)
|
||||
delete(s.unvalidatedOptimistic, event.Server)
|
||||
delete(s.unvalidatedFinality, event.Server)
|
||||
delete(s.reqFinalityEpoch, event.Server)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ const (
|
|||
ssNeedParent // cp header slot %32 != 0, need parent to check epoch boundary
|
||||
ssParentRequested // cp parent header requested
|
||||
ssPrintStatus // has all necessary info, print log message if init still not successful
|
||||
ssDone // log message printed, no more action required
|
||||
)
|
||||
|
||||
type serverState struct {
|
||||
|
|
@ -179,8 +180,7 @@ func (s *CheckpointInit) Process(requester request.Requester, events []request.E
|
|||
default:
|
||||
log.Error("blsync: checkpoint not available, but reported as finalized; specified checkpoint hash might be too old", "server", server.Name())
|
||||
}
|
||||
s.serverState[server] = serverState{state: ssDefault}
|
||||
requester.Fail(server, "checkpoint init failed")
|
||||
s.serverState[server] = serverState{state: ssDone}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
0xbb7a7f3c40d8ea0b450f91587db65d0f1c079669277e01a0426c8911702a863a
|
||||
0x1bbf958008172591b6cbdb3d8d52e26998258e83d4bdb9eec10969d84519a6bd
|
||||
|
|
@ -1 +1 @@
|
|||
0x2af778d703186526a1b6304b423f338f11556206f618643c3f7fa0d7b1ef5c9b
|
||||
0x2fe39a39b6f7cbd549e0f74d259de6db486005a65bd3bd92840dd6ce21d6f4c8
|
||||
|
|
@ -1 +1 @@
|
|||
0x48a89c9ea7ba19de2931797974cf8722344ab231c0edada278b108ef74125478
|
||||
0x86686b2b366e24134e0e3969a9c5f3759f92e5d2b04785b42e22cc7d468c2107
|
||||
|
|
@ -38,7 +38,7 @@ import (
|
|||
// across signing different data structures.
|
||||
const syncCommitteeDomain = 7
|
||||
|
||||
var knownForks = []string{"GENESIS", "ALTAIR", "BELLATRIX", "CAPELLA", "DENEB", "ELECTRA", "FULU"}
|
||||
var knownForks = []string{"GENESIS", "ALTAIR", "BELLATRIX", "CAPELLA", "DENEB"}
|
||||
|
||||
// ClientConfig contains beacon light client configuration.
|
||||
type ClientConfig struct {
|
||||
|
|
@ -103,16 +103,11 @@ func (c *ChainConfig) LoadForks(file []byte) error {
|
|||
epochs["GENESIS"] = 0
|
||||
|
||||
for key, value := range config {
|
||||
if value == nil {
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(key, "_FORK_VERSION") {
|
||||
name := key[:len(key)-len("_FORK_VERSION")]
|
||||
switch version := value.(type) {
|
||||
case int:
|
||||
versions[name] = new(big.Int).SetUint64(uint64(version)).FillBytes(make([]byte, 4))
|
||||
case int64:
|
||||
versions[name] = new(big.Int).SetUint64(uint64(version)).FillBytes(make([]byte, 4))
|
||||
case uint64:
|
||||
versions[name] = new(big.Int).SetUint64(version).FillBytes(make([]byte, 4))
|
||||
case string:
|
||||
|
|
@ -130,8 +125,6 @@ func (c *ChainConfig) LoadForks(file []byte) error {
|
|||
switch epoch := value.(type) {
|
||||
case int:
|
||||
epochs[name] = uint64(epoch)
|
||||
case int64:
|
||||
epochs[name] = uint64(epoch)
|
||||
case uint64:
|
||||
epochs[name] = epoch
|
||||
case string:
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@ ALTAIR_FORK_EPOCH: 1
|
|||
EIP7928_FORK_VERSION: 0xb0000038
|
||||
EIP7928_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
EIP7XXX_FORK_VERSION:
|
||||
EIP7XXX_FORK_EPOCH:
|
||||
|
||||
BLOB_SCHEDULE: []
|
||||
`
|
||||
c := &ChainConfig{}
|
||||
|
|
|
|||
|
|
@ -40,39 +40,36 @@ var (
|
|||
GenesisTime: 1606824023,
|
||||
Checkpoint: common.HexToHash(checkpointMainnet),
|
||||
}).
|
||||
AddFork("GENESIS", 0, common.FromHex("0x00000000")).
|
||||
AddFork("ALTAIR", 74240, common.FromHex("0x01000000")).
|
||||
AddFork("BELLATRIX", 144896, common.FromHex("0x02000000")).
|
||||
AddFork("CAPELLA", 194048, common.FromHex("0x03000000")).
|
||||
AddFork("DENEB", 269568, common.FromHex("0x04000000")).
|
||||
AddFork("ELECTRA", 364032, common.FromHex("0x05000000")).
|
||||
AddFork("FULU", 411392, common.FromHex("0x06000000"))
|
||||
AddFork("GENESIS", 0, []byte{0, 0, 0, 0}).
|
||||
AddFork("ALTAIR", 74240, []byte{1, 0, 0, 0}).
|
||||
AddFork("BELLATRIX", 144896, []byte{2, 0, 0, 0}).
|
||||
AddFork("CAPELLA", 194048, []byte{3, 0, 0, 0}).
|
||||
AddFork("DENEB", 269568, []byte{4, 0, 0, 0}).
|
||||
AddFork("ELECTRA", 364032, []byte{5, 0, 0, 0})
|
||||
|
||||
SepoliaLightConfig = (&ChainConfig{
|
||||
GenesisValidatorsRoot: common.HexToHash("0xd8ea171f3c94aea21ebc42a1ed61052acf3f9209c00e4efbaaddac09ed9b8078"),
|
||||
GenesisTime: 1655733600,
|
||||
Checkpoint: common.HexToHash(checkpointSepolia),
|
||||
}).
|
||||
AddFork("GENESIS", 0, common.FromHex("0x90000069")).
|
||||
AddFork("ALTAIR", 50, common.FromHex("0x90000070")).
|
||||
AddFork("BELLATRIX", 100, common.FromHex("0x90000071")).
|
||||
AddFork("CAPELLA", 56832, common.FromHex("0x90000072")).
|
||||
AddFork("DENEB", 132608, common.FromHex("0x90000073")).
|
||||
AddFork("ELECTRA", 222464, common.FromHex("0x90000074")).
|
||||
AddFork("FULU", 272640, common.FromHex("0x90000075"))
|
||||
AddFork("GENESIS", 0, []byte{144, 0, 0, 105}).
|
||||
AddFork("ALTAIR", 50, []byte{144, 0, 0, 112}).
|
||||
AddFork("BELLATRIX", 100, []byte{144, 0, 0, 113}).
|
||||
AddFork("CAPELLA", 56832, []byte{144, 0, 0, 114}).
|
||||
AddFork("DENEB", 132608, []byte{144, 0, 0, 115}).
|
||||
AddFork("ELECTRA", 222464, []byte{144, 0, 0, 116})
|
||||
|
||||
HoleskyLightConfig = (&ChainConfig{
|
||||
GenesisValidatorsRoot: common.HexToHash("0x9143aa7c615a7f7115e2b6aac319c03529df8242ae705fba9df39b79c59fa8b1"),
|
||||
GenesisTime: 1695902400,
|
||||
Checkpoint: common.HexToHash(checkpointHolesky),
|
||||
}).
|
||||
AddFork("GENESIS", 0, common.FromHex("0x01017000")).
|
||||
AddFork("ALTAIR", 0, common.FromHex("0x02017000")).
|
||||
AddFork("BELLATRIX", 0, common.FromHex("0x03017000")).
|
||||
AddFork("CAPELLA", 256, common.FromHex("0x04017000")).
|
||||
AddFork("DENEB", 29696, common.FromHex("0x05017000")).
|
||||
AddFork("ELECTRA", 115968, common.FromHex("0x06017000")).
|
||||
AddFork("FULU", 165120, common.FromHex("0x07017000"))
|
||||
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}).
|
||||
AddFork("ELECTRA", 115968, []byte{6, 1, 112, 0})
|
||||
|
||||
HoodiLightConfig = (&ChainConfig{
|
||||
GenesisValidatorsRoot: common.HexToHash("0x212f13fc4df078b6cb7db228f1c8307566dcecf900867401a92023d7ba99cb5f"),
|
||||
|
|
@ -85,5 +82,5 @@ var (
|
|||
AddFork("CAPELLA", 0, common.FromHex("0x40000910")).
|
||||
AddFork("DENEB", 0, common.FromHex("0x50000910")).
|
||||
AddFork("ELECTRA", 2048, common.FromHex("0x60000910")).
|
||||
AddFork("FULU", 50688, common.FromHex("0x70000910"))
|
||||
AddFork("FULU", 18446744073709551615, common.FromHex("0x70000910"))
|
||||
)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ func BlockFromJSON(forkName string, data []byte) (*BeaconBlock, error) {
|
|||
obj = new(capella.BeaconBlock)
|
||||
case "deneb":
|
||||
obj = new(deneb.BeaconBlock)
|
||||
case "electra", "fulu":
|
||||
case "electra":
|
||||
obj = new(electra.BeaconBlock)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported fork: %s", forkName)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ func ExecutionHeaderFromJSON(forkName string, data []byte) (*ExecutionHeader, er
|
|||
switch forkName {
|
||||
case "capella":
|
||||
obj = new(capella.ExecutionPayloadHeader)
|
||||
case "deneb", "electra", "fulu": // note: the payload type was not changed in electra/fulu
|
||||
case "deneb", "electra": // note: the payload type was not changed in electra
|
||||
obj = new(deneb.ExecutionPayloadHeader)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported fork: %s", forkName)
|
||||
|
|
|
|||
|
|
@ -5,102 +5,81 @@
|
|||
# https://github.com/ethereum/execution-spec-tests/releases/download/v5.1.0
|
||||
a3192784375acec7eaec492799d5c5d0c47a2909a3cc40178898e4ecd20cc416 fixtures_develop.tar.gz
|
||||
|
||||
# version:golang 1.25.9
|
||||
# version:golang 1.25.1
|
||||
# https://go.dev/dl/
|
||||
0ec9ef8ebcea097aac37decae9f09a7218b451cd96be7d6ed513d8e4bcf909cf go1.25.9.src.tar.gz
|
||||
b9ede6378a8f8d3d22bf52e68beb69ef7abdb65929ab2456020383002da15846 go1.25.9.aix-ppc64.tar.gz
|
||||
92cb78fba4796e218c1accb0ea0a214ef2094c382049a244ad6505505d015fbe go1.25.9.darwin-amd64.tar.gz
|
||||
9528be7329b9770631a6bd09ca2f3a73ed7332bec01d87435e75e92d8f130363 go1.25.9.darwin-arm64.tar.gz
|
||||
918e44a471c5524caa52f74185064240d5eb343aa8023d604776511fc7adffa6 go1.25.9.dragonfly-amd64.tar.gz
|
||||
2d67dbdfd09c6fcaa0e64485367ef43b8837ea200c663d6417183237bcddf83d go1.25.9.freebsd-386.tar.gz
|
||||
9152d0c0badbfeb0c0e148e47c12bec28099d8cf2db60958810c879e0b679d07 go1.25.9.freebsd-amd64.tar.gz
|
||||
437dca59604ad4a806a6a88e3d7ec1cd98ac9b402a3671629f4e553dd8b9888f go1.25.9.freebsd-arm.tar.gz
|
||||
4c0fe53977412036fc8081e8d0992bbaabe4d3e1926137271ba11c2f5753300f go1.25.9.freebsd-arm64.tar.gz
|
||||
d6087cdd1c084bd186132f29e0d032852a745f3c7619003d0fd5612c1fa58c8a go1.25.9.freebsd-riscv64.tar.gz
|
||||
f82e49037e195cb62beae6a6ad83497157b2af5a01bad2f1dcb65df41080aabb go1.25.9.illumos-amd64.tar.gz
|
||||
1e14a73bc2b19e370e0d4c57ba87aabfe8aef1e435e14d246742d48a13254f36 go1.25.9.linux-386.tar.gz
|
||||
00859d7bd6defe8bf84d9db9e57b9a4467b2887c18cd93ae7460e713db774bc1 go1.25.9.linux-amd64.tar.gz
|
||||
ec342e7389b7f489564ed5463c63b16cf8040023dabc7861256677165a8c0e2b go1.25.9.linux-arm64.tar.gz
|
||||
7d4f0d266d871301e08ef4ac31c56e66048688893b2848392e5c600276351ee8 go1.25.9.linux-armv6l.tar.gz
|
||||
f3460d901a14496bc609636e4accf9110ee1869d41c64af7e29cd567cffcf49b go1.25.9.linux-loong64.tar.gz
|
||||
1da96ea449382ff96c09c55cee74815324e01d687d5ac6d2ade58244b8574306 go1.25.9.linux-mips.tar.gz
|
||||
311a7f5f01f9a4bd51288b575eb619dc8e28e1fbc0cd78256a428b3ca668ff01 go1.25.9.linux-mips64.tar.gz
|
||||
0b4edaf9e2ba3f0a079547effda70ec6a4b51a6ca3271a1147652c87ebcf3735 go1.25.9.linux-mips64le.tar.gz
|
||||
42667340df264896f20b12261429d954e736e9772ab83ba289e68c30cf6f9628 go1.25.9.linux-mipsle.tar.gz
|
||||
b9cbb3a4894b5aca6966c23452608435e8535278ef019b18d8898fbbfab67e74 go1.25.9.linux-ppc64.tar.gz
|
||||
b0c41c7da1fc8d39020d65296a0dc54167afd9f76d67064e22c31ce3d839a739 go1.25.9.linux-ppc64le.tar.gz
|
||||
2a630be8f854177c13e5fa75f7812c721369ecb9bd6e4c0fb1bd1c708d08b37c go1.25.9.linux-riscv64.tar.gz
|
||||
0cf55136ac7eaccfc36d849054f849510ea289c2d959ffbed7b3866b4f484d17 go1.25.9.linux-s390x.tar.gz
|
||||
eaf8167ff10a6a3e5dd304ef5f2e020b3a7379e76fa1011dc49c895800bf367c go1.25.9.netbsd-386.tar.gz
|
||||
3cc6a861e62e23feae660984e0f2f14a2efb5d1f655900afee1d51af98919ae4 go1.25.9.netbsd-amd64.tar.gz
|
||||
c2c44dca10e882c30553f4aa2ab8f6722b670fb12882378c8f461a9105d40188 go1.25.9.netbsd-arm.tar.gz
|
||||
f301b71a8ec448053a5d2597df2e178120204bc9a33266c81600dd5d020a61b4 go1.25.9.netbsd-arm64.tar.gz
|
||||
c4543b7fdef9707b4896810c69b4160a43ecec210af45c300f3abd78aa0c9e72 go1.25.9.openbsd-386.tar.gz
|
||||
37275325e314f5ab7cf8ae65c4efc7cbfdaf20b41c6849549739b57a3ac97544 go1.25.9.openbsd-amd64.tar.gz
|
||||
f9c05b6b315e979ecdd47354dd287c01708d6a88dc6ae7af74c84df8fa00df94 go1.25.9.openbsd-arm.tar.gz
|
||||
4e999f42cf959ff95ca84af1ea1db3771000f5e57e157904bc2ffc72c75e29a2 go1.25.9.openbsd-arm64.tar.gz
|
||||
0c7fa6c7c2b1cc13ad32fa94fc31273b4adf39c1e0f0e5dcedac158ff526af3f go1.25.9.openbsd-ppc64.tar.gz
|
||||
347b33953a4b6e8df17719296f360f60878fe48a2d482ceb3637a3dfd4950065 go1.25.9.openbsd-riscv64.tar.gz
|
||||
889f77d567c06832e0d332fe2458653dc66d43cded7ddbca6f72ce0ca60029cc go1.25.9.plan9-386.tar.gz
|
||||
978b1f931fadec2f2516237d2649ee845d93c8eaf47dd196cfd8d26c7b2706a1 go1.25.9.plan9-amd64.tar.gz
|
||||
30b9565e5ad0a212fe00990ead700c751b416eb2ef8d7c91a204945a7ff83a48 go1.25.9.plan9-arm.tar.gz
|
||||
9e9125ff84ab3c3522ec758cab9540a17e9cba12bfcc34b6bf556cb89b522591 go1.25.9.solaris-amd64.tar.gz
|
||||
bf40515f5f4d834fa9ead31ff75581e61a38ac27bf49840b95c5c998d321c0f6 go1.25.9.windows-386.zip
|
||||
a7a710e225467b34e9e09fb432b829c86c9b2da5821ee5418f7eb2e8ae1a22cc go1.25.9.windows-amd64.zip
|
||||
33cd73cf1b3ceee655ef71bc96e94006c02ae3c617fdd67ac9be3dfae3957449 go1.25.9.windows-arm64.zip
|
||||
d010c109cee94d80efe681eab46bdea491ac906bf46583c32e9f0dbb0bd1a594 go1.25.1.src.tar.gz
|
||||
1d622468f767a1b9fe1e1e67bd6ce6744d04e0c68712adc689748bbeccb126bb go1.25.1.darwin-amd64.tar.gz
|
||||
68deebb214f39d542e518ebb0598a406ab1b5a22bba8ec9ade9f55fb4dd94a6c go1.25.1.darwin-arm64.tar.gz
|
||||
d03cdcbc9bd8baf5cf028de390478e9e2b3e4d0afe5a6582dedc19bfe6a263b2 go1.25.1.linux-386.tar.gz
|
||||
7716a0d940a0f6ae8e1f3b3f4f36299dc53e31b16840dbd171254312c41ca12e go1.25.1.linux-amd64.tar.gz
|
||||
65a3e34fb2126f55b34e1edfc709121660e1be2dee6bdf405fc399a63a95a87d go1.25.1.linux-arm64.tar.gz
|
||||
eb949be683e82a99e9861dafd7057e31ea40b161eae6c4cd18fdc0e8c4ae6225 go1.25.1.linux-armv6l.tar.gz
|
||||
be13d5479b8c75438f2efcaa8c191fba3af684b3228abc9c99c7aa8502f34424 go1.25.1.windows-386.zip
|
||||
4a974de310e7ee1d523d2fcedb114ba5fa75408c98eb3652023e55ccf3fa7cab go1.25.1.windows-amd64.zip
|
||||
45ab4290adbd6ee9e7f18f0d57eaa9008fdbef590882778ed93eac3c8cca06c5 go1.25.1.aix-ppc64.tar.gz
|
||||
2e3c1549bed3124763774d648f291ac42611232f48320ebbd23517c909c09b81 go1.25.1.dragonfly-amd64.tar.gz
|
||||
dc0198dd4ec520e13f26798def8750544edf6448d8e9c43fd2a814e4885932af go1.25.1.freebsd-386.tar.gz
|
||||
c4f1a7e7b258406e6f3b677ecdbd97bbb23ff9c0d44be4eb238a07d360f69ac8 go1.25.1.freebsd-amd64.tar.gz
|
||||
7772fc5ff71ed39297ec0c1599fc54e399642c9b848eac989601040923b0de9c go1.25.1.freebsd-arm.tar.gz
|
||||
5bb011d5d5b6218b12189f07aa0be618ab2002662fff1ca40afba7389735c207 go1.25.1.freebsd-arm64.tar.gz
|
||||
ccac716240cb049bebfafcb7eebc3758512178a4c51fc26da9cc032035d850c8 go1.25.1.freebsd-riscv64.tar.gz
|
||||
cc53910ffb9fcfdd988a9fa25b5423bae1cfa01b19616be646700e1f5453b466 go1.25.1.illumos-amd64.tar.gz
|
||||
efe809f923bcedab44bf7be2b3af8d182b512b1bf9c07d302e0c45d26c8f56f3 go1.25.1.linux-loong64.tar.gz
|
||||
c0de33679f6ed68991dc42dc4a602e74a666e3e166c1748ee1b5d1a7ea2ffbb2 go1.25.1.linux-mips.tar.gz
|
||||
c270f7b0c0bdfbcd54fef4481227c40d41bb518f9ae38ee930870f04a0a6a589 go1.25.1.linux-mips64.tar.gz
|
||||
80be871ba9c944f34d1868cdf5047e1cf2e1289fe08cdb90e2453d2f0d6965ae go1.25.1.linux-mips64le.tar.gz
|
||||
9f09defa9bb22ebf2cde76162f40958564e57ce5c2b3649bc063bebcbc9294c1 go1.25.1.linux-mipsle.tar.gz
|
||||
2c76b7d278c1d43ad19d478ad3f0f05e7b782b64b90870701b314fa48b5f43c6 go1.25.1.linux-ppc64.tar.gz
|
||||
8b0c8d3ee5b1b5c28b6bd63dc4438792012e01d03b4bf7a61d985c87edab7d1f go1.25.1.linux-ppc64le.tar.gz
|
||||
22fe934a9d0c9c57275716c55b92d46ebd887cec3177c9140705efa9f84ba1e2 go1.25.1.linux-riscv64.tar.gz
|
||||
9cfe517ba423f59f3738ca5c3d907c103253cffbbcc2987142f79c5de8c1bf93 go1.25.1.linux-s390x.tar.gz
|
||||
6af8a08353e76205d5b743dd7a3f0126684f96f62be0a31b75daf9837e512c46 go1.25.1.netbsd-386.tar.gz
|
||||
e5d534ff362edb1bd8c8e10892b6a027c4c1482454245d1529167676498684c7 go1.25.1.netbsd-amd64.tar.gz
|
||||
88bcf39254fdcea6a199c1c27d787831b652427ce60851ae9e41a3d7eb477f45 go1.25.1.netbsd-arm.tar.gz
|
||||
d7c2eabe1d04ee47bcaea2816fdd90dbd25d90d4dfa756faa9786c788e4f3a4e go1.25.1.netbsd-arm64.tar.gz
|
||||
14a2845977eb4dde11d929858c437a043467c427db87899935e90cee04a38d72 go1.25.1.openbsd-386.tar.gz
|
||||
d27ac54b38a13a09c81e67c82ac70d387037341c85c3399291c73e13e83fdd8c go1.25.1.openbsd-amd64.tar.gz
|
||||
0f4ab5f02500afa4befd51fed1e8b45e4d07ca050f641cc3acc76eaa4027b2c3 go1.25.1.openbsd-arm.tar.gz
|
||||
d46c3bd156843656f7f3cb0dec27ea51cd926ec3f7b80744bf8156e67c1c812f go1.25.1.openbsd-arm64.tar.gz
|
||||
c550514c67f22e409be10e40eace761e2e43069f4ef086ae6e60aac736c2b679 go1.25.1.openbsd-ppc64.tar.gz
|
||||
8a09a8714a2556eb13fc1f10b7ce2553fcea4971e3330fc3be0efd24aab45734 go1.25.1.openbsd-riscv64.tar.gz
|
||||
b0e1fefaf0c7abd71f139a54eee9767944aff5f0bc9d69c968234804884e552f go1.25.1.plan9-386.tar.gz
|
||||
e94732c94f149690aa0ab11c26090577211b4a988137cb2c03ec0b54e750402e go1.25.1.plan9-amd64.tar.gz
|
||||
7eb80e9de1e817d9089a54e8c7c5c8d8ed9e5fb4d4a012fc0f18fc422a484f0c go1.25.1.plan9-arm.tar.gz
|
||||
1261dfad7c4953c0ab90381bc1242dc54e394db7485c59349428d532b2273343 go1.25.1.solaris-amd64.tar.gz
|
||||
04bc3c078e9e904c4d58d6ac2532a5bdd402bd36a9ff0b5949b3c5e6006a05ee go1.25.1.windows-arm64.zip
|
||||
|
||||
# version:golangci 2.10.1
|
||||
# version:golangci 2.4.0
|
||||
# https://github.com/golangci/golangci-lint/releases/
|
||||
# https://github.com/golangci/golangci-lint/releases/download/v2.10.1
|
||||
66fb0da81b8033b477f97eea420d4b46b230ca172b8bb87c6610109f3772b6b6 golangci-lint-2.10.1-darwin-amd64.tar.gz
|
||||
03bfadf67e52b441b7ec21305e501c717df93c959836d66c7f97312654acb297 golangci-lint-2.10.1-darwin-arm64.tar.gz
|
||||
c9a44658ccc8f7b8dbbd4ae6020ba91c1a5d3987f4d91ced0f7d2bea013e57ca golangci-lint-2.10.1-freebsd-386.tar.gz
|
||||
a513c5cb4e0f5bd5767001af9d5e97e7868cfc2d9c46739a4df93e713cfb24af golangci-lint-2.10.1-freebsd-amd64.tar.gz
|
||||
2ef38eefc4b5cee2febacb75a30579526e5656c16338a921d80e59a8e87d4425 golangci-lint-2.10.1-freebsd-arm64.tar.gz
|
||||
8fea6766318b4829e766bbe325f10191d75297dcc44ae35bf374816037878e38 golangci-lint-2.10.1-freebsd-armv6.tar.gz
|
||||
30b629870574d6254f3e8804e5a74b34f98e1263c9d55465830d739c88b862ed golangci-lint-2.10.1-freebsd-armv7.tar.gz
|
||||
c0db839f866ce80b1b6c96167aa101cfe50d9c936f42d942a3c1cbdc1801af68 golangci-lint-2.10.1-illumos-amd64.tar.gz
|
||||
280eb56636e9175f671cd7b755d7d67f628ae2ed00a164d1e443c43c112034e5 golangci-lint-2.10.1-linux-386.deb
|
||||
065a7d99da61dc7dfbfef2e2d7053dd3fa6672598f2747117aa4bb5f45e7df7f golangci-lint-2.10.1-linux-386.rpm
|
||||
a55918c03bb413b2662287653ab2ae2fef4e37428b247dad6348724adde9d770 golangci-lint-2.10.1-linux-386.tar.gz
|
||||
8aa9b3aa14f39745eeb7fc7ff50bcac683e785397d1e4bc9afd2184b12c4ce86 golangci-lint-2.10.1-linux-amd64.deb
|
||||
62a111688e9e305032334a2cbc84f4d971b64bb3bffc99d3f80081d57fb25e32 golangci-lint-2.10.1-linux-amd64.rpm
|
||||
dfa775874cf0561b404a02a8f4481fc69b28091da95aa697259820d429b09c99 golangci-lint-2.10.1-linux-amd64.tar.gz
|
||||
b3f36937e8ea1660739dc0f5c892ea59c9c21ed4e75a91a25957c561f7f79a55 golangci-lint-2.10.1-linux-arm64.deb
|
||||
36d50314d53683b1f1a2a6cedfb5a9468451b481c64ab9e97a8e843ea088074d golangci-lint-2.10.1-linux-arm64.rpm
|
||||
6652b42ae02915eb2f9cb2a2e0cac99514c8eded8388d88ae3e06e1a52c00de8 golangci-lint-2.10.1-linux-arm64.tar.gz
|
||||
a32d8d318e803496812dd3461f250e52ccc7f53c47b95ce404a9cf55778ceb6a golangci-lint-2.10.1-linux-armv6.deb
|
||||
41d065f4c8ea165a1531abea644988ee2e973e4f0b49f9725ed3b979dac45112 golangci-lint-2.10.1-linux-armv6.rpm
|
||||
59159a4df03aabbde69d15c7b7b3df143363cbb41f4bd4b200caffb8e34fb734 golangci-lint-2.10.1-linux-armv6.tar.gz
|
||||
b2e8ec0e050a1e2251dfe1561434999d202f5a3f9fa47ce94378b0fd1662ea5a golangci-lint-2.10.1-linux-armv7.deb
|
||||
28c9331429a497da27e9c77846063bd0e8275e878ffedb4eb9e9f21d24771cc0 golangci-lint-2.10.1-linux-armv7.rpm
|
||||
818f33e95b273e3769284b25563b51ef6a294e9e25acf140fda5830c075a1a59 golangci-lint-2.10.1-linux-armv7.tar.gz
|
||||
6b6b85ed4b7c27f51097dd681523000409dde835e86e6e314e87be4bb013e2ab golangci-lint-2.10.1-linux-loong64.deb
|
||||
94050a0cf06169e2ae44afb307dcaafa7d7c3b38c0c23b5652cf9cb60f0c337f golangci-lint-2.10.1-linux-loong64.rpm
|
||||
25820300fccb8c961c1cdcb1f77928040c079e04c43a3a5ceb34b1cb4a1c5c8d golangci-lint-2.10.1-linux-loong64.tar.gz
|
||||
98bf39d10139fdcaa37f94950e9bbb8888660ae468847ae0bf1cb5bf67c1f68b golangci-lint-2.10.1-linux-mips64.deb
|
||||
df3ce5f03808dcceaa8b683d1d06e95c885f09b59dc8e15deb840fbe2b3e3299 golangci-lint-2.10.1-linux-mips64.rpm
|
||||
972508dda523067e6e6a1c8e6609d63bc7c4153819c11b947d439235cf17bac2 golangci-lint-2.10.1-linux-mips64.tar.gz
|
||||
1d37f2919e183b5bf8b1777ed8c4b163d3b491d0158355a7999d647655cbbeb6 golangci-lint-2.10.1-linux-mips64le.deb
|
||||
e341d031002cd09a416329ed40f674231051a38544b8f94deb2d1708ce1f4a6f golangci-lint-2.10.1-linux-mips64le.rpm
|
||||
393560122b9cb5538df0c357d30eb27b6ee563533fbb9b138c8db4fd264002af golangci-lint-2.10.1-linux-mips64le.tar.gz
|
||||
21ca46b6a96442e8957677a3ca059c6b93674a68a01b1c71f4e5df0ea2e96d19 golangci-lint-2.10.1-linux-ppc64le.deb
|
||||
57fe0cbca0a9bbdf1547c5e8aa7d278e6896b438d72a541bae6bc62c38b43d1e golangci-lint-2.10.1-linux-ppc64le.rpm
|
||||
e2883db9fa51584e5e203c64456f29993550a7faadc84e3faccdb48f0669992e golangci-lint-2.10.1-linux-ppc64le.tar.gz
|
||||
aa6da0e98ab0ba3bb7582e112174c349907d5edfeff90a551dca3c6eecf92fc0 golangci-lint-2.10.1-linux-riscv64.deb
|
||||
3c68d76cd884a7aad206223a980b9c20bb9ea74b560fa27ed02baf2389189234 golangci-lint-2.10.1-linux-riscv64.rpm
|
||||
3bca11bfac4197205639cbd4676a5415054e629ac6c12ea10fcbe33ef852d9c3 golangci-lint-2.10.1-linux-riscv64.tar.gz
|
||||
0c6aed2ce49db2586adbac72c80d871f06feb1caf4c0763a5ca98fec809a8f0b golangci-lint-2.10.1-linux-s390x.deb
|
||||
16c285adfe1061d69dd8e503be69f87c7202857c6f4add74ac02e3571158fbec golangci-lint-2.10.1-linux-s390x.rpm
|
||||
21011ad368eb04f024201b832095c6b5f96d0888de194cca5bfe4d9307d6364b golangci-lint-2.10.1-linux-s390x.tar.gz
|
||||
7b5191e77a70485918712e31ed55159956323e4911bab1b67569c9d86e1b75eb golangci-lint-2.10.1-netbsd-386.tar.gz
|
||||
07801fd38d293ebad10826f8285525a39ea91ce5ddad77d05bfa90bda9c884a9 golangci-lint-2.10.1-netbsd-amd64.tar.gz
|
||||
7e7219d71c1bf33b98c328c93dc0560706dd896a1c43c44696e5222fc9d7446e golangci-lint-2.10.1-netbsd-arm64.tar.gz
|
||||
92fbc90b9eec0e572269b0f5492a2895c426b086a68372fde49b7e4d4020863e golangci-lint-2.10.1-netbsd-armv6.tar.gz
|
||||
f67b3ae1f47caeefa507a4ebb0c8336958a19011fe48766443212030f75d004b golangci-lint-2.10.1-netbsd-armv7.tar.gz
|
||||
a40bc091c10cea84eaee1a90b84b65f5e8652113b0a600bb099e4e4d9d7caddb golangci-lint-2.10.1-windows-386.zip
|
||||
c60c87695e79db8e320f0e5be885059859de52bb5ee5f11be5577828570bc2a3 golangci-lint-2.10.1-windows-amd64.zip
|
||||
636ab790c8dcea8034aa34aba6031ca3893d68f7eda000460ab534341fadbab1 golangci-lint-2.10.1-windows-arm64.zip
|
||||
# https://github.com/golangci/golangci-lint/releases/download/v2.4.0/
|
||||
7904ce63f79db44934939cf7a063086ea0ea98e9b19eba0a9d52ccdd0d21951c golangci-lint-2.4.0-darwin-amd64.tar.gz
|
||||
cd4dd53fa09b6646baff5fd22b8c64d91db02c21c7496df27992d75d34feec59 golangci-lint-2.4.0-darwin-arm64.tar.gz
|
||||
d58f426ebe14cc257e81562b4bf37a488ffb4ffbbb3ec73041eb3b38bb25c0e1 golangci-lint-2.4.0-freebsd-386.tar.gz
|
||||
6ec4a6177fc6c0dd541fbcb3a7612845266d020d35cc6fa92959220cdf64ca39 golangci-lint-2.4.0-freebsd-amd64.tar.gz
|
||||
4d473e3e71c01feaa915a0604fb35758b41284fb976cdeac3f842118d9ee7e17 golangci-lint-2.4.0-freebsd-armv6.tar.gz
|
||||
58727746c6530801a3f9a702a5945556a5eb7e88809222536dd9f9d54cafaeff golangci-lint-2.4.0-freebsd-armv7.tar.gz
|
||||
fbf28c662760e24c32f82f8d16dffdb4a82de7726a52ba1fad94f890c22997ea golangci-lint-2.4.0-illumos-amd64.tar.gz
|
||||
a15a000a8981ef665e971e0f67e2acda9066a9e37a59344393b7351d8fb49c81 golangci-lint-2.4.0-linux-386.tar.gz
|
||||
fae792524c04424c0ac369f5b8076f04b45cf29fc945a370e55d369a8dc11840 golangci-lint-2.4.0-linux-amd64.tar.gz
|
||||
70ac11f55b80ec78fd3a879249cc9255121b8dfd7f7ed4fc46ed137f4abf17e7 golangci-lint-2.4.0-linux-arm64.tar.gz
|
||||
4acdc40e5cebe99e4e7ced358a05b2e71789f409b41cb4f39bbb86ccfa14b1dc golangci-lint-2.4.0-linux-armv6.tar.gz
|
||||
2a68749568fa22b4a97cb88dbea655595563c795076536aa6c087f7968784bf3 golangci-lint-2.4.0-linux-armv7.tar.gz
|
||||
9e3369afb023711036dcb0b4f45c9fe2792af962fa1df050c9f6ac101a6c5d73 golangci-lint-2.4.0-linux-loong64.tar.gz
|
||||
bb9143d6329be2c4dbfffef9564078e7da7d88e7dde6c829b6263d98e072229e golangci-lint-2.4.0-linux-mips64.tar.gz
|
||||
5ad1765b40d56cd04d4afd805b3ba6f4bfd9b36181da93c31e9b17e483d8608d golangci-lint-2.4.0-linux-mips64le.tar.gz
|
||||
918936fb9c0d5ba96bef03cf4348b03938634cfcced49be1e9bb29cb5094fa73 golangci-lint-2.4.0-linux-ppc64le.tar.gz
|
||||
f7474c638e1fb67ebbdc654b55ca0125377ea0bc88e8fee8d964a4f24eacf828 golangci-lint-2.4.0-linux-riscv64.tar.gz
|
||||
b617a9543997c8bfceaffa88a75d4e595030c6add69fba800c1e4d8f5fe253dd golangci-lint-2.4.0-linux-s390x.tar.gz
|
||||
7db027b03a9ba328f795215b04f594036837bc7dd0dd7cd16776b02a6167981c golangci-lint-2.4.0-netbsd-386.tar.gz
|
||||
52d8f9393f4313df0a62b752c37775e3af0b818e43e8dd28954351542d7c60bc golangci-lint-2.4.0-netbsd-amd64.tar.gz
|
||||
5c0086027fb5a4af3829e530c8115db4b35d11afe1914322eef528eb8cd38c69 golangci-lint-2.4.0-netbsd-arm64.tar.gz
|
||||
6b779d6ed1aed87cefe195cc11759902b97a76551b593312c6833f2635a3488f golangci-lint-2.4.0-netbsd-armv6.tar.gz
|
||||
f00d1f4b7ec3468a0f9fffd0d9ea036248b029b7621cbc9a59c449ef94356d09 golangci-lint-2.4.0-netbsd-armv7.tar.gz
|
||||
3ce671b0b42b58e35066493aab75a7e2826c9e079988f1ba5d814a4029faaf87 golangci-lint-2.4.0-windows-386.zip
|
||||
003112f7a56746feaabf20b744054bf9acdf900c9e77176383623c4b1d76aaa9 golangci-lint-2.4.0-windows-amd64.zip
|
||||
dc0c2092af5d47fc2cd31a1dfe7b4c7e765fab22de98bd21ef2ffcc53ad9f54f golangci-lint-2.4.0-windows-arm64.zip
|
||||
0263d23e20a260cb1592d35e12a388f99efe2c51b3611fdc66fbd9db1fce664d golangci-lint-2.4.0-windows-armv6.zip
|
||||
9403c03bf648e6313036e0273149d44bad1b9ad53889b6d00e4ccb842ba3c058 golangci-lint-2.4.0-windows-armv7.zip
|
||||
|
||||
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
|
||||
#
|
||||
|
|
|
|||
163
build/ci.go
163
build/ci.go
|
|
@ -31,9 +31,6 @@ Available commands are:
|
|||
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
|
||||
test [ -coverage ] [ packages... ] -- runs the tests
|
||||
|
||||
keeper [ -dlgo ]
|
||||
keeper-archive [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ]
|
||||
|
||||
archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts
|
||||
importkeys -- imports signing keys from env
|
||||
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
|
||||
|
|
@ -89,46 +86,6 @@ var (
|
|||
executablePath("clef"),
|
||||
}
|
||||
|
||||
// Keeper build targets with their configurations
|
||||
keeperTargets = []struct {
|
||||
Name string
|
||||
GOOS string
|
||||
GOARCH string
|
||||
CC string
|
||||
Tags string
|
||||
Env map[string]string
|
||||
}{
|
||||
{
|
||||
Name: "ziren",
|
||||
GOOS: "linux",
|
||||
GOARCH: "mipsle",
|
||||
// enable when cgo works
|
||||
// CC: "mipsel-linux-gnu-gcc",
|
||||
Tags: "ziren",
|
||||
Env: map[string]string{"GOMIPS": "softfloat", "CGO_ENABLED": "0"},
|
||||
},
|
||||
{
|
||||
Name: "womir",
|
||||
GOOS: "wasip1",
|
||||
GOARCH: "wasm",
|
||||
Tags: "womir",
|
||||
},
|
||||
{
|
||||
Name: "wasm-js",
|
||||
GOOS: "js",
|
||||
GOARCH: "wasm",
|
||||
},
|
||||
{
|
||||
Name: "wasm-wasi",
|
||||
GOOS: "wasip1",
|
||||
GOARCH: "wasm",
|
||||
},
|
||||
{
|
||||
Name: "example",
|
||||
Tags: "example",
|
||||
},
|
||||
}
|
||||
|
||||
// A debian package is created for all executables listed here.
|
||||
debExecutables = []debExecutable{
|
||||
{
|
||||
|
|
@ -167,11 +124,13 @@ var (
|
|||
|
||||
// Distros for which packages are created
|
||||
debDistros = []string{
|
||||
"xenial", // 16.04, EOL: 04/2026
|
||||
"bionic", // 18.04, EOL: 04/2028
|
||||
"focal", // 20.04, EOL: 04/2030
|
||||
"jammy", // 22.04, EOL: 04/2032
|
||||
"noble", // 24.04, EOL: 04/2034
|
||||
"xenial", // 16.04, EOL: 04/2026
|
||||
"bionic", // 18.04, EOL: 04/2028
|
||||
"focal", // 20.04, EOL: 04/2030
|
||||
"jammy", // 22.04, EOL: 04/2032
|
||||
"noble", // 24.04, EOL: 04/2034
|
||||
"oracular", // 24.10, EOL: 07/2025
|
||||
"plucky", // 25.04, EOL: 01/2026
|
||||
}
|
||||
|
||||
// This is where the tests should be unpacked.
|
||||
|
|
@ -219,10 +178,6 @@ func main() {
|
|||
doPurge(os.Args[2:])
|
||||
case "sanitycheck":
|
||||
doSanityCheck()
|
||||
case "keeper":
|
||||
doInstallKeeper(os.Args[2:])
|
||||
case "keeper-archive":
|
||||
doKeeperArchive(os.Args[2:])
|
||||
default:
|
||||
log.Fatal("unknown command ", os.Args[1])
|
||||
}
|
||||
|
|
@ -257,6 +212,9 @@ func doInstall(cmdline []string) {
|
|||
// Configure the build.
|
||||
gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...)
|
||||
|
||||
// We use -trimpath to avoid leaking local paths into the built executables.
|
||||
gobuild.Args = append(gobuild.Args, "-trimpath")
|
||||
|
||||
// Show packages during build.
|
||||
gobuild.Args = append(gobuild.Args, "-v")
|
||||
|
||||
|
|
@ -276,43 +234,6 @@ func doInstall(cmdline []string) {
|
|||
}
|
||||
}
|
||||
|
||||
// doInstallKeeper builds keeper binaries for all supported targets.
|
||||
func doInstallKeeper(cmdline []string) {
|
||||
var dlgo = flag.Bool("dlgo", false, "Download Go and build with it")
|
||||
|
||||
flag.CommandLine.Parse(cmdline)
|
||||
env := build.Env()
|
||||
|
||||
// Configure the toolchain.
|
||||
tc := build.GoToolchain{}
|
||||
if *dlgo {
|
||||
csdb := download.MustLoadChecksums("build/checksums.txt")
|
||||
tc.Root = build.DownloadGo(csdb)
|
||||
}
|
||||
|
||||
for _, target := range keeperTargets {
|
||||
log.Printf("Building keeper-%s", target.Name)
|
||||
|
||||
// Configure the build.
|
||||
tc.GOARCH = target.GOARCH
|
||||
tc.GOOS = target.GOOS
|
||||
tc.CC = target.CC
|
||||
gobuild := tc.Go("build", buildFlags(env, true, []string{target.Tags})...)
|
||||
gobuild.Dir = "./cmd/keeper"
|
||||
gobuild.Args = append(gobuild.Args, "-v")
|
||||
|
||||
for key, value := range target.Env {
|
||||
gobuild.Env = append(gobuild.Env, key+"="+value)
|
||||
}
|
||||
outputName := fmt.Sprintf("keeper-%s", target.Name)
|
||||
|
||||
args := slices.Clone(gobuild.Args)
|
||||
args = append(args, "-o", executablePath(outputName))
|
||||
args = append(args, ".")
|
||||
build.MustRun(&exec.Cmd{Path: gobuild.Path, Args: args, Env: gobuild.Env, Dir: gobuild.Dir})
|
||||
}
|
||||
}
|
||||
|
||||
// buildFlags returns the go tool flags for building.
|
||||
func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (flags []string) {
|
||||
var ld []string
|
||||
|
|
@ -345,18 +266,12 @@ func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (
|
|||
}
|
||||
ld = append(ld, "-extldflags", "'"+strings.Join(extld, " ")+"'")
|
||||
}
|
||||
// TODO(gballet): revisit after the input api has been defined
|
||||
if runtime.GOARCH == "wasm" {
|
||||
ld = append(ld, "-gcflags=all=-d=softfloat")
|
||||
}
|
||||
if len(ld) > 0 {
|
||||
flags = append(flags, "-ldflags", strings.Join(ld, " "))
|
||||
}
|
||||
if len(buildTags) > 0 {
|
||||
flags = append(flags, "-tags", strings.Join(buildTags, ","))
|
||||
}
|
||||
// We use -trimpath to avoid leaking local paths into the built executables.
|
||||
flags = append(flags, "-trimpath")
|
||||
return flags
|
||||
}
|
||||
|
||||
|
|
@ -366,15 +281,16 @@ func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (
|
|||
|
||||
func doTest(cmdline []string) {
|
||||
var (
|
||||
dlgo = flag.Bool("dlgo", false, "Download Go and build with it")
|
||||
arch = flag.String("arch", "", "Run tests for given architecture")
|
||||
cc = flag.String("cc", "", "Sets C compiler binary")
|
||||
coverage = flag.Bool("coverage", false, "Whether to record code coverage")
|
||||
verbose = flag.Bool("v", false, "Whether to log verbosely")
|
||||
race = flag.Bool("race", false, "Execute the race detector")
|
||||
short = flag.Bool("short", false, "Pass the 'short'-flag to go test")
|
||||
cachedir = flag.String("cachedir", "./build/cache", "directory for caching downloads")
|
||||
threads = flag.Int("p", 1, "Number of CPU threads to use for testing")
|
||||
dlgo = flag.Bool("dlgo", false, "Download Go and build with it")
|
||||
arch = flag.String("arch", "", "Run tests for given architecture")
|
||||
cc = flag.String("cc", "", "Sets C compiler binary")
|
||||
coverage = flag.Bool("coverage", false, "Whether to record code coverage")
|
||||
verbose = flag.Bool("v", false, "Whether to log verbosely")
|
||||
race = flag.Bool("race", false, "Execute the race detector")
|
||||
short = flag.Bool("short", false, "Pass the 'short'-flag to go test")
|
||||
cachedir = flag.String("cachedir", "./build/cache", "directory for caching downloads")
|
||||
skipspectests = flag.Bool("skip-spectests", false, "Skip downloading execution-spec-tests fixtures")
|
||||
threads = flag.Int("p", 1, "Number of CPU threads to use for testing")
|
||||
)
|
||||
flag.CommandLine.Parse(cmdline)
|
||||
|
||||
|
|
@ -382,7 +298,7 @@ func doTest(cmdline []string) {
|
|||
csdb := download.MustLoadChecksums("build/checksums.txt")
|
||||
|
||||
// Get test fixtures.
|
||||
if !*short {
|
||||
if !*skipspectests {
|
||||
downloadSpecTestFixtures(csdb, *cachedir)
|
||||
}
|
||||
|
||||
|
|
@ -464,14 +380,9 @@ func doCheckGenerate() {
|
|||
)
|
||||
pathList := []string{filepath.Join(protocPath, "bin"), protocGenGoPath, os.Getenv("PATH")}
|
||||
|
||||
excludes := []string{"tests/testdata", "build/cache", ".git"}
|
||||
for i := range excludes {
|
||||
excludes[i] = filepath.FromSlash(excludes[i])
|
||||
}
|
||||
|
||||
for _, mod := range goModules {
|
||||
// Compute the origin hashes of all the files
|
||||
hashes, err := build.HashFolder(mod, excludes)
|
||||
hashes, err := build.HashFolder(mod, []string{"tests/testdata", "build/cache", ".git"})
|
||||
if err != nil {
|
||||
log.Fatal("Error computing hashes", "err", err)
|
||||
}
|
||||
|
|
@ -481,7 +392,7 @@ func doCheckGenerate() {
|
|||
c.Dir = mod
|
||||
build.MustRun(c)
|
||||
// Check if generate file hashes have changed
|
||||
generated, err := build.HashFolder(mod, excludes)
|
||||
generated, err := build.HashFolder(mod, []string{"tests/testdata", "build/cache", ".git"})
|
||||
if err != nil {
|
||||
log.Fatalf("Error re-computing hashes: %v", err)
|
||||
}
|
||||
|
|
@ -719,32 +630,6 @@ func doArchive(cmdline []string) {
|
|||
}
|
||||
}
|
||||
|
||||
func doKeeperArchive(cmdline []string) {
|
||||
var (
|
||||
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`)
|
||||
signify = flag.String("signify", "", `Environment variable holding the signify key (e.g. LINUX_SIGNIFY_KEY)`)
|
||||
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
|
||||
)
|
||||
flag.CommandLine.Parse(cmdline)
|
||||
|
||||
var (
|
||||
env = build.Env()
|
||||
vsn = version.Archive(env.Commit)
|
||||
keeper = "keeper-" + vsn + ".tar.gz"
|
||||
)
|
||||
maybeSkipArchive(env)
|
||||
files := []string{"COPYING"}
|
||||
for _, target := range keeperTargets {
|
||||
files = append(files, executablePath(fmt.Sprintf("keeper-%s", target.Name)))
|
||||
}
|
||||
if err := build.WriteArchive(keeper, files); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := archiveUpload(keeper, *upload, *signer, *signify); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func archiveBasename(arch string, archiveVersion string) string {
|
||||
platform := runtime.GOOS + "-" + arch
|
||||
if arch == "arm" {
|
||||
|
|
@ -1200,7 +1085,7 @@ func doWindowsInstaller(cmdline []string) {
|
|||
var (
|
||||
arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging")
|
||||
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`)
|
||||
signify = flag.String("signify", "", `Environment variable holding the signify signing key (e.g. WINDOWS_SIGNIFY_KEY)`)
|
||||
signify = flag.String("signify key", "", `Environment variable holding the signify signing key (e.g. WINDOWS_SIGNIFY_KEY)`)
|
||||
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
|
||||
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
|
||||
)
|
||||
|
|
|
|||
32
circle.yml
Normal file
32
circle.yml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
machine:
|
||||
services:
|
||||
- docker
|
||||
|
||||
dependencies:
|
||||
cache_directories:
|
||||
- "~/.ethash" # Cache the ethash DAG generated by hive for consecutive builds
|
||||
- "~/.docker" # Cache all docker images manually to avoid lengthy rebuilds
|
||||
override:
|
||||
# Restore all previously cached docker images
|
||||
- mkdir -p ~/.docker
|
||||
- for img in `ls ~/.docker`; do docker load -i ~/.docker/$img; done
|
||||
|
||||
# Pull in and hive, restore cached ethash DAGs and do a dry run
|
||||
- go get -u github.com/karalabe/hive
|
||||
- (cd ~/.go_workspace/src/github.com/karalabe/hive && mkdir -p workspace/ethash/ ~/.ethash)
|
||||
- (cd ~/.go_workspace/src/github.com/karalabe/hive && cp -r ~/.ethash/. workspace/ethash/)
|
||||
- (cd ~/.go_workspace/src/github.com/karalabe/hive && hive --docker-noshell --client=NONE --test=. --sim=. --loglevel=6)
|
||||
|
||||
# Cache all the docker images and the ethash DAGs
|
||||
- for img in `docker images | grep -v "^<none>" | tail -n +2 | awk '{print $1}'`; do docker save $img > ~/.docker/`echo $img | tr '/' ':'`.tar; done
|
||||
- cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/ethash/. ~/.ethash
|
||||
|
||||
test:
|
||||
override:
|
||||
# Build Geth and move into a known folder
|
||||
- make geth
|
||||
- cp ./build/bin/geth $HOME/geth
|
||||
|
||||
# Run hive and move all generated logs into the public artifacts folder
|
||||
- (cd ~/.go_workspace/src/github.com/karalabe/hive && hive --docker-noshell --client=go-ethereum:local --override=$HOME/geth --test=. --sim=.)
|
||||
- cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/logs/* $CIRCLE_ARTIFACTS
|
||||
|
|
@ -121,7 +121,7 @@ with our test chain. The chain files are located in `./cmd/devp2p/internal/ethte
|
|||
--nat=none \
|
||||
--networkid 3503995874084926 \
|
||||
--verbosity 5 \
|
||||
--authrpc.jwtsecret jwt.secret
|
||||
--authrpc.jwtsecret 0x7365637265747365637265747365637265747365637265747365637265747365
|
||||
|
||||
Note that the tests also require access to the engine API.
|
||||
The test suite can now be executed using the devp2p tool.
|
||||
|
|
@ -130,7 +130,7 @@ The test suite can now be executed using the devp2p tool.
|
|||
--chain internal/ethtest/testdata \
|
||||
--node enode://.... \
|
||||
--engineapi http://127.0.0.1:8551 \
|
||||
--jwtsecret $(cat jwt.secret)
|
||||
--jwtsecret 0x7365637265747365637265747365637265747365637265747365637265747365
|
||||
|
||||
Repeat the above process (re-initialising the node) in order to run the Eth Protocol test suite again.
|
||||
|
||||
|
|
|
|||
|
|
@ -51,12 +51,6 @@ type Chain struct {
|
|||
state map[common.Address]state.DumpAccount // state of head block
|
||||
senders map[common.Address]*senderInfo
|
||||
config *params.ChainConfig
|
||||
|
||||
txInfo txInfo
|
||||
}
|
||||
|
||||
type txInfo struct {
|
||||
LargeReceiptBlock *uint64 `json:"tx-largereceipt"`
|
||||
}
|
||||
|
||||
// NewChain takes the given chain.rlp file, and decodes and returns
|
||||
|
|
@ -80,20 +74,12 @@ func NewChain(dir string) (*Chain, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var txInfo txInfo
|
||||
err = common.LoadJSON(filepath.Join(dir, "txinfo.json"), &txInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Chain{
|
||||
genesis: gen,
|
||||
blocks: blocks,
|
||||
state: state,
|
||||
senders: accounts,
|
||||
config: gen.Config,
|
||||
txInfo: txInfo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,10 +66,9 @@ func (s *Suite) dialAs(key *ecdsa.PrivateKey) (*Conn, error) {
|
|||
return nil, err
|
||||
}
|
||||
conn.caps = []p2p.Cap{
|
||||
{Name: "eth", Version: 70},
|
||||
{Name: "eth", Version: 69},
|
||||
}
|
||||
conn.ourHighestProtoVersion = 70
|
||||
conn.ourHighestProtoVersion = 69
|
||||
return &conn, nil
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +155,7 @@ func (c *Conn) ReadEth() (any, error) {
|
|||
var msg any
|
||||
switch int(code) {
|
||||
case eth.StatusMsg:
|
||||
msg = new(eth.StatusPacket)
|
||||
msg = new(eth.StatusPacket69)
|
||||
case eth.GetBlockHeadersMsg:
|
||||
msg = new(eth.GetBlockHeadersPacket)
|
||||
case eth.BlockHeadersMsg:
|
||||
|
|
@ -165,6 +164,10 @@ func (c *Conn) ReadEth() (any, error) {
|
|||
msg = new(eth.GetBlockBodiesPacket)
|
||||
case eth.BlockBodiesMsg:
|
||||
msg = new(eth.BlockBodiesPacket)
|
||||
case eth.NewBlockMsg:
|
||||
msg = new(eth.NewBlockPacket)
|
||||
case eth.NewBlockHashesMsg:
|
||||
msg = new(eth.NewBlockHashesPacket)
|
||||
case eth.TransactionsMsg:
|
||||
msg = new(eth.TransactionsPacket)
|
||||
case eth.NewPooledTransactionHashesMsg:
|
||||
|
|
@ -226,7 +229,7 @@ func (c *Conn) ReadSnap() (any, error) {
|
|||
}
|
||||
|
||||
// dialAndPeer creates a peer connection and runs the handshake.
|
||||
func (s *Suite) dialAndPeer(status *eth.StatusPacket) (*Conn, error) {
|
||||
func (s *Suite) dialAndPeer(status *eth.StatusPacket69) (*Conn, error) {
|
||||
c, err := s.dial()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -239,7 +242,7 @@ func (s *Suite) dialAndPeer(status *eth.StatusPacket) (*Conn, error) {
|
|||
|
||||
// peer performs both the protocol handshake and the status message
|
||||
// exchange with the node in order to peer with it.
|
||||
func (c *Conn) peer(chain *Chain, status *eth.StatusPacket) error {
|
||||
func (c *Conn) peer(chain *Chain, status *eth.StatusPacket69) error {
|
||||
if err := c.handshake(); err != nil {
|
||||
return fmt.Errorf("handshake failed: %v", err)
|
||||
}
|
||||
|
|
@ -312,7 +315,7 @@ func (c *Conn) negotiateEthProtocol(caps []p2p.Cap) {
|
|||
}
|
||||
|
||||
// statusExchange performs a `Status` message exchange with the given node.
|
||||
func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket) error {
|
||||
func (c *Conn) statusExchange(chain *Chain, status *eth.StatusPacket69) error {
|
||||
loop:
|
||||
for {
|
||||
code, data, err := c.Read()
|
||||
|
|
@ -321,7 +324,7 @@ loop:
|
|||
}
|
||||
switch code {
|
||||
case eth.StatusMsg + protoOffset(ethProto):
|
||||
msg := new(eth.StatusPacket)
|
||||
msg := new(eth.StatusPacket69)
|
||||
if err := rlp.DecodeBytes(data, &msg); err != nil {
|
||||
return fmt.Errorf("error decoding status packet: %w", err)
|
||||
}
|
||||
|
|
@ -336,12 +339,10 @@ loop:
|
|||
if have, want := msg.ForkID, chain.ForkID(); !reflect.DeepEqual(have, want) {
|
||||
return fmt.Errorf("wrong fork ID in status: have %v, want %v", have, want)
|
||||
}
|
||||
for _, cap := range c.caps {
|
||||
if cap.Name == "eth" && cap.Version == uint(msg.ProtocolVersion) {
|
||||
break loop
|
||||
}
|
||||
if have, want := msg.ProtocolVersion, c.ourHighestProtoVersion; have != uint32(want) {
|
||||
return fmt.Errorf("wrong protocol version: have %v, want %v", have, want)
|
||||
}
|
||||
return fmt.Errorf("wrong protocol version: have %v, want %v", msg.ProtocolVersion, c.caps)
|
||||
break loop
|
||||
case discMsg:
|
||||
var msg []p2p.DiscReason
|
||||
if rlp.DecodeBytes(data, &msg); len(msg) == 0 {
|
||||
|
|
@ -362,7 +363,7 @@ loop:
|
|||
}
|
||||
if status == nil {
|
||||
// default status message
|
||||
status = ð.StatusPacket{
|
||||
status = ð.StatusPacket69{
|
||||
ProtocolVersion: uint32(c.negotiatedProtoVersion),
|
||||
NetworkID: chain.config.ChainID.Uint64(),
|
||||
Genesis: chain.blocks[0].Hash(),
|
||||
|
|
|
|||
|
|
@ -86,3 +86,9 @@ func protoOffset(proto Proto) uint64 {
|
|||
panic("unhandled protocol")
|
||||
}
|
||||
}
|
||||
|
||||
// msgTypePtr is the constraint for protocol message types.
|
||||
type msgTypePtr[U any] interface {
|
||||
*U
|
||||
Kind() byte
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth/protocols/snap"
|
||||
"github.com/ethereum/go-ethereum/internal/utesting"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
)
|
||||
|
|
@ -87,9 +86,9 @@ func (s *Suite) TestSnapGetAccountRange(t *utesting.T) {
|
|||
root: root,
|
||||
startingHash: zero,
|
||||
limitHash: ffHash,
|
||||
expAccounts: 68,
|
||||
expAccounts: 67,
|
||||
expFirst: firstKey,
|
||||
expLast: common.HexToHash("0x59312f89c13e9e24c1cb8b103aa39a9b2800348d97a92c2c9e2a78fa02b70025"),
|
||||
expLast: common.HexToHash("0x622e662246601dd04f996289ce8b85e86db7bb15bb17f86487ec9d543ddb6f9a"),
|
||||
desc: "In this test, we request the entire state range, but limit the response to 4000 bytes.",
|
||||
},
|
||||
{
|
||||
|
|
@ -97,9 +96,9 @@ func (s *Suite) TestSnapGetAccountRange(t *utesting.T) {
|
|||
root: root,
|
||||
startingHash: zero,
|
||||
limitHash: ffHash,
|
||||
expAccounts: 50,
|
||||
expAccounts: 49,
|
||||
expFirst: firstKey,
|
||||
expLast: common.HexToHash("0x4615e5f5df5b25349a00ad313c6cd0436b6c08ee5826e33a018661997f85ebaa"),
|
||||
expLast: common.HexToHash("0x445cb5c1278fdce2f9cbdb681bdd76c52f8e50e41dbd9e220242a69ba99ac099"),
|
||||
desc: "In this test, we request the entire state range, but limit the response to 3000 bytes.",
|
||||
},
|
||||
{
|
||||
|
|
@ -107,9 +106,9 @@ func (s *Suite) TestSnapGetAccountRange(t *utesting.T) {
|
|||
root: root,
|
||||
startingHash: zero,
|
||||
limitHash: ffHash,
|
||||
expAccounts: 35,
|
||||
expAccounts: 34,
|
||||
expFirst: firstKey,
|
||||
expLast: common.HexToHash("0x2de4bdbddcfbb9c3e195dae6b45f9c38daff897e926764bf34887fb0db5c3284"),
|
||||
expLast: common.HexToHash("0x2ef46ebd2073cecde499c2e8df028ad79a26d57bfaa812c4c6f7eb4c9617b913"),
|
||||
desc: "In this test, we request the entire state range, but limit the response to 2000 bytes.",
|
||||
},
|
||||
{
|
||||
|
|
@ -178,9 +177,9 @@ The server should return the first available account.`,
|
|||
root: root,
|
||||
startingHash: firstKey,
|
||||
limitHash: ffHash,
|
||||
expAccounts: 68,
|
||||
expAccounts: 67,
|
||||
expFirst: firstKey,
|
||||
expLast: common.HexToHash("0x59312f89c13e9e24c1cb8b103aa39a9b2800348d97a92c2c9e2a78fa02b70025"),
|
||||
expLast: common.HexToHash("0x622e662246601dd04f996289ce8b85e86db7bb15bb17f86487ec9d543ddb6f9a"),
|
||||
desc: `In this test, startingHash is exactly the first available account key.
|
||||
The server should return the first available account of the state as the first item.`,
|
||||
},
|
||||
|
|
@ -189,9 +188,9 @@ The server should return the first available account of the state as the first i
|
|||
root: root,
|
||||
startingHash: hashAdd(firstKey, 1),
|
||||
limitHash: ffHash,
|
||||
expAccounts: 68,
|
||||
expAccounts: 67,
|
||||
expFirst: secondKey,
|
||||
expLast: common.HexToHash("0x59a7c8818f1c16b298a054020dc7c3f403a970d1d1db33f9478b1c36e3a2e509"),
|
||||
expLast: common.HexToHash("0x66192e4c757fba1cdc776e6737008f42d50370d3cd801db3624274283bf7cd63"),
|
||||
desc: `In this test, startingHash is after the first available key.
|
||||
The server should return the second account of the state as the first item.`,
|
||||
},
|
||||
|
|
@ -227,9 +226,9 @@ server to return no data because genesis is older than 127 blocks.`,
|
|||
root: s.chain.RootAt(int(s.chain.Head().Number().Uint64()) - 127),
|
||||
startingHash: zero,
|
||||
limitHash: ffHash,
|
||||
expAccounts: 68,
|
||||
expAccounts: 66,
|
||||
expFirst: firstKey,
|
||||
expLast: common.HexToHash("0x683b6c03cc32afe5db8cb96050f711fdaff8f8ff44c7587a9a848f921d02815e"),
|
||||
expLast: common.HexToHash("0x729953a43ed6c913df957172680a17e5735143ad767bda8f58ac84ec62fbec5e"),
|
||||
desc: `This test requests data at a state root that is 127 blocks old.
|
||||
We expect the server to have this state available.`,
|
||||
},
|
||||
|
|
@ -658,8 +657,8 @@ The server should reject the request.`,
|
|||
// It's a bit unfortunate these are hard-coded, but the result depends on
|
||||
// a lot of aspects of the state trie and can't be guessed in a simple
|
||||
// way. So you'll have to update this when the test chain is changed.
|
||||
common.HexToHash("0x4bdecec09691ad38113eebee2df94fadefdff5841c0f182bae1be3c8a6d60bf3"),
|
||||
common.HexToHash("0x4178696465d4514ff5924ef8c28ce64d41a669634b63184c2c093e252d6b4bc4"),
|
||||
common.HexToHash("0x5bdc0d6057b35642a16d27223ea5454e5a17a400e28f7328971a5f2a87773b76"),
|
||||
common.HexToHash("0x0a76c9812ca90ffed8ee4d191e683f93386b6e50cfe3679c0760d27510aa7fc5"),
|
||||
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
|
||||
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
|
||||
empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty, empty,
|
||||
|
|
@ -679,8 +678,8 @@ The server should reject the request.`,
|
|||
// be updated when the test chain is changed.
|
||||
expHashes: []common.Hash{
|
||||
empty,
|
||||
common.HexToHash("0x4178696465d4514ff5924ef8c28ce64d41a669634b63184c2c093e252d6b4bc4"),
|
||||
common.HexToHash("0x4bdecec09691ad38113eebee2df94fadefdff5841c0f182bae1be3c8a6d60bf3"),
|
||||
common.HexToHash("0x0a76c9812ca90ffed8ee4d191e683f93386b6e50cfe3679c0760d27510aa7fc5"),
|
||||
common.HexToHash("0x5bdc0d6057b35642a16d27223ea5454e5a17a400e28f7328971a5f2a87773b76"),
|
||||
},
|
||||
},
|
||||
|
||||
|
|
@ -938,14 +937,10 @@ func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error {
|
|||
}
|
||||
|
||||
// write0 request
|
||||
paths, err := rlp.EncodeToRawList(tc.paths)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
req := &snap.GetTrieNodesPacket{
|
||||
ID: uint64(rand.Int63()),
|
||||
Root: tc.root,
|
||||
Paths: paths,
|
||||
Paths: tc.paths,
|
||||
Bytes: tc.nBytes,
|
||||
}
|
||||
msg, err := conn.snapRequest(snap.GetTrieNodesMsg, req)
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/internal/utesting"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
|
|
@ -84,7 +82,6 @@ func (s *Suite) EthTests() []utesting.Test {
|
|||
// get history
|
||||
{Name: "GetBlockBodies", Fn: s.TestGetBlockBodies},
|
||||
{Name: "GetReceipts", Fn: s.TestGetReceipts},
|
||||
{Name: "GetLargeReceipts", Fn: s.TestGetLargeReceipts},
|
||||
// test transactions
|
||||
{Name: "LargeTxRequest", Fn: s.TestLargeTxRequest, Slow: true},
|
||||
{Name: "Transaction", Fn: s.TestTransaction},
|
||||
|
|
@ -154,11 +151,7 @@ func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to get headers for given request: %v", err)
|
||||
}
|
||||
received, err := headers.List.Items()
|
||||
if err != nil {
|
||||
t.Fatalf("invalid headers received: %v", err)
|
||||
}
|
||||
if !headersMatch(expected, received) {
|
||||
if !headersMatch(expected, headers.BlockHeadersRequest) {
|
||||
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers)
|
||||
}
|
||||
}
|
||||
|
|
@ -244,7 +237,7 @@ concurrently, with different request IDs.`)
|
|||
|
||||
// Wait for responses.
|
||||
// Note they can arrive in either order.
|
||||
resp, err := collectHeaderResponses(conn, 2, func(msg *eth.BlockHeadersPacket) uint64 {
|
||||
resp, err := collectResponses(conn, 2, func(msg *eth.BlockHeadersPacket) uint64 {
|
||||
if msg.RequestId != 111 && msg.RequestId != 222 {
|
||||
t.Fatalf("response with unknown request ID: %v", msg.RequestId)
|
||||
}
|
||||
|
|
@ -255,11 +248,17 @@ concurrently, with different request IDs.`)
|
|||
}
|
||||
|
||||
// Check if headers match.
|
||||
if err := s.checkHeadersAgainstChain(req1, resp[111]); err != nil {
|
||||
t.Fatal(err)
|
||||
resp1 := resp[111]
|
||||
if expected, err := s.chain.GetHeaders(req1); err != nil {
|
||||
t.Fatalf("failed to get expected headers for request 1: %v", err)
|
||||
} else if !headersMatch(expected, resp1.BlockHeadersRequest) {
|
||||
t.Fatalf("header mismatch for request ID %v: \nexpected %v \ngot %v", 111, expected, resp1)
|
||||
}
|
||||
if err := s.checkHeadersAgainstChain(req2, resp[222]); err != nil {
|
||||
t.Fatal(err)
|
||||
resp2 := resp[222]
|
||||
if expected, err := s.chain.GetHeaders(req2); err != nil {
|
||||
t.Fatalf("failed to get expected headers for request 2: %v", err)
|
||||
} else if !headersMatch(expected, resp2.BlockHeadersRequest) {
|
||||
t.Fatalf("header mismatch for request ID %v: \nexpected %v \ngot %v", 222, expected, resp2)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -304,8 +303,8 @@ same request ID. The node should handle the request by responding to both reques
|
|||
|
||||
// Wait for the responses. They can arrive in either order, and we can't tell them
|
||||
// apart by their request ID, so use the number of headers instead.
|
||||
resp, err := collectHeaderResponses(conn, 2, func(msg *eth.BlockHeadersPacket) uint64 {
|
||||
id := uint64(msg.List.Len())
|
||||
resp, err := collectResponses(conn, 2, func(msg *eth.BlockHeadersPacket) uint64 {
|
||||
id := uint64(len(msg.BlockHeadersRequest))
|
||||
if id != 2 && id != 3 {
|
||||
t.Fatalf("invalid number of headers in response: %d", id)
|
||||
}
|
||||
|
|
@ -316,35 +315,26 @@ same request ID. The node should handle the request by responding to both reques
|
|||
}
|
||||
|
||||
// Check if headers match.
|
||||
if err := s.checkHeadersAgainstChain(request1, resp[2]); err != nil {
|
||||
t.Fatal(err)
|
||||
resp1 := resp[2]
|
||||
if expected, err := s.chain.GetHeaders(request1); err != nil {
|
||||
t.Fatalf("failed to get expected headers for request 1: %v", err)
|
||||
} else if !headersMatch(expected, resp1.BlockHeadersRequest) {
|
||||
t.Fatalf("headers mismatch: \nexpected %v \ngot %v", expected, resp1)
|
||||
}
|
||||
if err := s.checkHeadersAgainstChain(request2, resp[3]); err != nil {
|
||||
t.Fatal(err)
|
||||
resp2 := resp[3]
|
||||
if expected, err := s.chain.GetHeaders(request2); err != nil {
|
||||
t.Fatalf("failed to get expected headers for request 2: %v", err)
|
||||
} else if !headersMatch(expected, resp2.BlockHeadersRequest) {
|
||||
t.Fatalf("headers mismatch: \nexpected %v \ngot %v", expected, resp2)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Suite) checkHeadersAgainstChain(req *eth.GetBlockHeadersPacket, resp *eth.BlockHeadersPacket) error {
|
||||
received2, err := resp.List.Items()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid headers in response with request ID %v (%d items): %v", resp.RequestId, resp.List.Len(), err)
|
||||
}
|
||||
if expected, err := s.chain.GetHeaders(req); err != nil {
|
||||
return fmt.Errorf("test chain failed to get expected headers for request: %v", err)
|
||||
} else if !headersMatch(expected, received2) {
|
||||
return fmt.Errorf("header mismatch for request ID %v (%d items): \nexpected %v \ngot %v", resp.RequestId, resp.List.Len(), expected, resp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// collectResponses waits for n messages of type T on the given connection.
|
||||
// The messsages are collected according to the 'identity' function.
|
||||
//
|
||||
// This function is written in a generic way to handle
|
||||
func collectHeaderResponses(conn *Conn, n int, identity func(*eth.BlockHeadersPacket) uint64) (map[uint64]*eth.BlockHeadersPacket, error) {
|
||||
resp := make(map[uint64]*eth.BlockHeadersPacket, n)
|
||||
func collectResponses[T any, P msgTypePtr[T]](conn *Conn, n int, identity func(P) uint64) (map[uint64]P, error) {
|
||||
resp := make(map[uint64]P, n)
|
||||
for range n {
|
||||
r := new(eth.BlockHeadersPacket)
|
||||
r := new(T)
|
||||
if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, r); err != nil {
|
||||
return resp, fmt.Errorf("read error: %v", err)
|
||||
}
|
||||
|
|
@ -383,8 +373,10 @@ and expects a response.`)
|
|||
if got, want := headers.RequestId, req.RequestId; got != want {
|
||||
t.Fatalf("unexpected request id")
|
||||
}
|
||||
if err := s.checkHeadersAgainstChain(req, headers); err != nil {
|
||||
t.Fatal(err)
|
||||
if expected, err := s.chain.GetHeaders(req); err != nil {
|
||||
t.Fatalf("failed to get expected block headers: %v", err)
|
||||
} else if !headersMatch(expected, headers.BlockHeadersRequest) {
|
||||
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -415,8 +407,9 @@ func (s *Suite) TestGetBlockBodies(t *utesting.T) {
|
|||
if got, want := resp.RequestId, req.RequestId; got != want {
|
||||
t.Fatalf("unexpected request id in respond", got, want)
|
||||
}
|
||||
if resp.List.Len() != len(req.GetBlockBodiesRequest) {
|
||||
t.Fatalf("wrong bodies in response: expected %d bodies, got %d", len(req.GetBlockBodiesRequest), resp.List.Len())
|
||||
bodies := resp.BlockBodiesResponse
|
||||
if len(bodies) != len(req.GetBlockBodiesRequest) {
|
||||
t.Fatalf("wrong bodies in response: expected %d bodies, got %d", len(req.GetBlockBodiesRequest), len(bodies))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -431,9 +424,6 @@ func (s *Suite) TestGetReceipts(t *utesting.T) {
|
|||
// Find some blocks containing receipts.
|
||||
var hashes = make([]common.Hash, 0, 3)
|
||||
for i := range s.chain.Len() {
|
||||
if s.chain.txInfo.LargeReceiptBlock != nil && uint64(i) == *s.chain.txInfo.LargeReceiptBlock {
|
||||
continue
|
||||
}
|
||||
block := s.chain.GetBlock(i)
|
||||
if len(block.Transactions()) > 0 {
|
||||
hashes = append(hashes, block.Hash())
|
||||
|
|
@ -442,121 +432,25 @@ func (s *Suite) TestGetReceipts(t *utesting.T) {
|
|||
break
|
||||
}
|
||||
}
|
||||
if conn.negotiatedProtoVersion < eth.ETH70 {
|
||||
// Create block bodies request.
|
||||
req := ð.GetReceiptsPacket69{
|
||||
RequestId: 66,
|
||||
GetReceiptsRequest: (eth.GetReceiptsRequest)(hashes),
|
||||
}
|
||||
if err := conn.Write(ethProto, eth.GetReceiptsMsg, req); err != nil {
|
||||
t.Fatalf("could not write to connection: %v", err)
|
||||
}
|
||||
// Wait for response.
|
||||
resp := new(eth.ReceiptsPacket69)
|
||||
if err := conn.ReadMsg(ethProto, eth.ReceiptsMsg, &resp); err != nil {
|
||||
t.Fatalf("error reading block receipts msg: %v", err)
|
||||
}
|
||||
if got, want := resp.RequestId, req.RequestId; got != want {
|
||||
t.Fatalf("unexpected request id in respond", got, want)
|
||||
}
|
||||
if resp.List.Len() != len(req.GetReceiptsRequest) {
|
||||
t.Fatalf("wrong receipts in response: expected %d receipts, got %d", len(req.GetReceiptsRequest), resp.List.Len())
|
||||
}
|
||||
} else {
|
||||
// Create block bodies request.
|
||||
req := ð.GetReceiptsPacket70{
|
||||
RequestId: 66,
|
||||
FirstBlockReceiptIndex: 0,
|
||||
GetReceiptsRequest: (eth.GetReceiptsRequest)(hashes),
|
||||
}
|
||||
if err := conn.Write(ethProto, eth.GetReceiptsMsg, req); err != nil {
|
||||
t.Fatalf("could not write to connection: %v", err)
|
||||
}
|
||||
// Wait for response.
|
||||
resp := new(eth.ReceiptsPacket70)
|
||||
if err := conn.ReadMsg(ethProto, eth.ReceiptsMsg, &resp); err != nil {
|
||||
t.Fatalf("error reading block receipts msg: %v", err)
|
||||
}
|
||||
if got, want := resp.RequestId, req.RequestId; got != want {
|
||||
t.Fatalf("unexpected request id in respond", got, want)
|
||||
}
|
||||
if resp.List.Len() != len(req.GetReceiptsRequest) {
|
||||
t.Fatalf("wrong receipts in response: expected %d receipts, got %d", len(req.GetReceiptsRequest), resp.List.Len())
|
||||
}
|
||||
|
||||
// Create block bodies request.
|
||||
req := ð.GetReceiptsPacket{
|
||||
RequestId: 66,
|
||||
GetReceiptsRequest: (eth.GetReceiptsRequest)(hashes),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Suite) TestGetLargeReceipts(t *utesting.T) {
|
||||
t.Log(`This test sends GetReceipts requests to the node for large receipt (>10MiB) in the test chain.
|
||||
This test is meaningful only if the client supports protocol version ETH70 or higher
|
||||
and LargeReceiptBlock is configured in txInfo.json.`)
|
||||
conn, err := s.dialAndPeer(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("peering failed: %v", err)
|
||||
if err := conn.Write(ethProto, eth.GetReceiptsMsg, req); err != nil {
|
||||
t.Fatalf("could not write to connection: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
if conn.negotiatedProtoVersion < eth.ETH70 || s.chain.txInfo.LargeReceiptBlock == nil {
|
||||
return
|
||||
// Wait for response.
|
||||
resp := new(eth.ReceiptsPacket[*eth.ReceiptList69])
|
||||
if err := conn.ReadMsg(ethProto, eth.ReceiptsMsg, &resp); err != nil {
|
||||
t.Fatalf("error reading block bodies msg: %v", err)
|
||||
}
|
||||
|
||||
// Find block with large receipt.
|
||||
// Place the large receipt block hash in the middle of the query
|
||||
start := max(int(*s.chain.txInfo.LargeReceiptBlock)-2, 0)
|
||||
end := min(*s.chain.txInfo.LargeReceiptBlock+2, uint64(len(s.chain.blocks)))
|
||||
|
||||
var blocks []common.Hash
|
||||
var receiptHashes []common.Hash
|
||||
var receipts []*eth.ReceiptList
|
||||
|
||||
for i := uint64(start); i < end; i++ {
|
||||
block := s.chain.GetBlock(int(i))
|
||||
blocks = append(blocks, block.Hash())
|
||||
receiptHashes = append(receiptHashes, block.Header().ReceiptHash)
|
||||
receipts = append(receipts, ð.ReceiptList{})
|
||||
if got, want := resp.RequestId, req.RequestId; got != want {
|
||||
t.Fatalf("unexpected request id in respond", got, want)
|
||||
}
|
||||
|
||||
incomplete := false
|
||||
lastBlock := 0
|
||||
|
||||
for incomplete || lastBlock != len(blocks)-1 {
|
||||
// Create get receipt request.
|
||||
req := ð.GetReceiptsPacket70{
|
||||
RequestId: 66,
|
||||
FirstBlockReceiptIndex: uint64(receipts[lastBlock].Derivable().Len()),
|
||||
GetReceiptsRequest: blocks[lastBlock:],
|
||||
}
|
||||
if err := conn.Write(ethProto, eth.GetReceiptsMsg, req); err != nil {
|
||||
t.Fatalf("could not write to connection: %v", err)
|
||||
}
|
||||
// Wait for response.
|
||||
resp := new(eth.ReceiptsPacket70)
|
||||
if err := conn.ReadMsg(ethProto, eth.ReceiptsMsg, &resp); err != nil {
|
||||
t.Fatalf("error reading block receipts msg: %v", err)
|
||||
}
|
||||
if got, want := resp.RequestId, req.RequestId; got != want {
|
||||
t.Fatalf("unexpected request id in respond, want: %d, got: %d", got, want)
|
||||
}
|
||||
|
||||
receiptLists, _ := resp.List.Items()
|
||||
for i, rc := range receiptLists {
|
||||
receipts[lastBlock+i].Append(rc)
|
||||
}
|
||||
lastBlock += len(receiptLists) - 1
|
||||
|
||||
incomplete = resp.LastBlockIncomplete
|
||||
}
|
||||
|
||||
hasher := trie.NewStackTrie(nil)
|
||||
hashes := make([]common.Hash, len(receipts))
|
||||
for i := range receipts {
|
||||
hashes[i] = types.DeriveSha(receipts[i].Derivable(), hasher)
|
||||
}
|
||||
|
||||
for i, hash := range hashes {
|
||||
if receiptHashes[i] != hash {
|
||||
t.Fatalf("wrong receipt root: want %x, got %x", receiptHashes[i], hash)
|
||||
}
|
||||
if len(resp.List) != len(req.GetReceiptsRequest) {
|
||||
t.Fatalf("wrong bodies in response: expected %d bodies, got %d", len(req.GetReceiptsRequest), len(resp.List))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -910,11 +804,7 @@ on another peer connection using GetPooledTransactions.`)
|
|||
if got, want := msg.RequestId, req.RequestId; got != want {
|
||||
t.Fatalf("unexpected request id in response: got %d, want %d", got, want)
|
||||
}
|
||||
responseTxs, err := msg.List.Items()
|
||||
if err != nil {
|
||||
t.Fatalf("invalid transactions in response: %v", err)
|
||||
}
|
||||
for _, got := range responseTxs {
|
||||
for _, got := range msg.PooledTransactionsResponse {
|
||||
if _, exists := set[got.Hash()]; !exists {
|
||||
t.Fatalf("unexpected tx received: %v", got.Hash())
|
||||
}
|
||||
|
|
@ -1086,9 +976,7 @@ func (s *Suite) TestBlobViolations(t *utesting.T) {
|
|||
if err := conn.ReadMsg(ethProto, eth.GetPooledTransactionsMsg, req); err != nil {
|
||||
t.Fatalf("reading pooled tx request failed: %v", err)
|
||||
}
|
||||
|
||||
encTxs, _ := rlp.EncodeToRawList(test.resp)
|
||||
resp := eth.PooledTransactionsPacket{RequestId: req.RequestId, List: encTxs}
|
||||
resp := eth.PooledTransactionsPacket{RequestId: req.RequestId, PooledTransactionsResponse: test.resp}
|
||||
if err := conn.Write(ethProto, eth.PooledTransactionsMsg, resp); err != nil {
|
||||
t.Fatalf("writing pooled tx response failed: %v", err)
|
||||
}
|
||||
|
|
@ -1216,8 +1104,7 @@ func (s *Suite) testBadBlobTx(t *utesting.T, tx *types.Transaction, badTx *types
|
|||
// the good peer is connected, and has announced the tx.
|
||||
// proceed to send the incorrect one from the bad peer.
|
||||
|
||||
encTxs, _ := rlp.EncodeToRawList([]*types.Transaction{badTx})
|
||||
resp := eth.PooledTransactionsPacket{RequestId: req.RequestId, List: encTxs}
|
||||
resp := eth.PooledTransactionsPacket{RequestId: req.RequestId, PooledTransactionsResponse: eth.PooledTransactionsResponse(types.Transactions{badTx})}
|
||||
if err := conn.Write(ethProto, eth.PooledTransactionsMsg, resp); err != nil {
|
||||
errc <- fmt.Errorf("writing pooled tx response failed: %v", err)
|
||||
return
|
||||
|
|
@ -1277,8 +1164,7 @@ func (s *Suite) testBadBlobTx(t *utesting.T, tx *types.Transaction, badTx *types
|
|||
return
|
||||
}
|
||||
|
||||
encTxs, _ := rlp.EncodeToRawList([]*types.Transaction{tx})
|
||||
resp := eth.PooledTransactionsPacket{RequestId: req.RequestId, List: encTxs}
|
||||
resp := eth.PooledTransactionsPacket{RequestId: req.RequestId, PooledTransactionsResponse: eth.PooledTransactionsResponse(types.Transactions{tx})}
|
||||
if err := conn.Write(ethProto, eth.PooledTransactionsMsg, resp); err != nil {
|
||||
errc <- fmt.Errorf("writing pooled tx response failed: %v", err)
|
||||
return
|
||||
|
|
|
|||
BIN
cmd/devp2p/internal/ethtest/testdata/chain.rlp
vendored
BIN
cmd/devp2p/internal/ethtest/testdata/chain.rlp
vendored
Binary file not shown.
|
|
@ -37,7 +37,7 @@
|
|||
"nonce": "0x0",
|
||||
"timestamp": "0x0",
|
||||
"extraData": "0x68697665636861696e",
|
||||
"gasLimit": "0x11e1a300",
|
||||
"gasLimit": "0x23f3e20",
|
||||
"difficulty": "0x20000",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||
|
|
@ -119,10 +119,6 @@
|
|||
"balance": "0x1",
|
||||
"nonce": "0x1"
|
||||
},
|
||||
"8dcd17433742f4c0ca53122ab541d0ba67fc27ff": {
|
||||
"code": "0x6202e6306000a0",
|
||||
"balance": "0x0"
|
||||
},
|
||||
"c7b99a164efd027a93f147376cc7da7c67c6bbe0": {
|
||||
"balance": "0xc097ce7bc90715b34b9f1000000000"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
{
|
||||
"parentHash": "0x7e80093a491eba0e5b2c1895837902f64f514100221801318fe391e1e09c96a6",
|
||||
"parentHash": "0x65151b101682b54cd08ba226f640c14c86176865ff9bfc57e0147dadaeac34bb",
|
||||
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"miner": "0x0000000000000000000000000000000000000000",
|
||||
"stateRoot": "0x8fcfb02cfca007773bd55bc1c3e50a3c8612a59c87ce057e5957e8bf17c1728b",
|
||||
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot": "0xce423ebc60fc7764a43f09f1fe3ae61eef25e3eb8d09b1108f7e7eb77dfff5e6",
|
||||
"transactionsRoot": "0x7ec1ae3989efa75d7bcc766e5e2443afa8a89a5fda42ebba90050e7e702980f7",
|
||||
"receiptsRoot": "0xfe160832b1ca85f38c6674cb0aae3a24693bc49be56e2ecdf3698b71a794de86",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"difficulty": "0x0",
|
||||
"number": "0x258",
|
||||
"gasLimit": "0x11e1a300",
|
||||
"gasUsed": "0x0",
|
||||
"gasLimit": "0x23f3e20",
|
||||
"gasUsed": "0x19d36",
|
||||
"timestamp": "0x1770",
|
||||
"extraData": "0x",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"nonce": "0x0000000000000000",
|
||||
"baseFeePerGas": "0x7",
|
||||
"withdrawalsRoot": "0x92abfda39de7df7d705c5a8f30386802ad59d31e782a06d5c5b0f9a260056cf0",
|
||||
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"blobGasUsed": "0x0",
|
||||
"excessBlobGas": "0x0",
|
||||
"parentBeaconBlockRoot": "0xf5003fc8f92358e790a114bce93ce1d9c283c85e1787f8d7d56714d3489b49e6",
|
||||
"requestsHash": "0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"hash": "0x44e3809c9a3cda717f00aea3a9da336d149612c8d5657fbc0028176ef8d94d2a"
|
||||
"hash": "0xce8d86ba17a2ec303155f0e264c58a4b8f94ce3436274cf1924f91acdb7502d0"
|
||||
}
|
||||
|
|
@ -4,9 +4,9 @@
|
|||
"method": "engine_forkchoiceUpdatedV3",
|
||||
"params": [
|
||||
{
|
||||
"headBlockHash": "0x44e3809c9a3cda717f00aea3a9da336d149612c8d5657fbc0028176ef8d94d2a",
|
||||
"safeBlockHash": "0x44e3809c9a3cda717f00aea3a9da336d149612c8d5657fbc0028176ef8d94d2a",
|
||||
"finalizedBlockHash": "0x44e3809c9a3cda717f00aea3a9da336d149612c8d5657fbc0028176ef8d94d2a"
|
||||
"headBlockHash": "0xce8d86ba17a2ec303155f0e264c58a4b8f94ce3436274cf1924f91acdb7502d0",
|
||||
"safeBlockHash": "0xce8d86ba17a2ec303155f0e264c58a4b8f94ce3436274cf1924f91acdb7502d0",
|
||||
"finalizedBlockHash": "0xce8d86ba17a2ec303155f0e264c58a4b8f94ce3436274cf1924f91acdb7502d0"
|
||||
},
|
||||
null
|
||||
]
|
||||
|
|
|
|||
4220
cmd/devp2p/internal/ethtest/testdata/headstate.json
vendored
4220
cmd/devp2p/internal/ethtest/testdata/headstate.json
vendored
File diff suppressed because it is too large
Load diff
10313
cmd/devp2p/internal/ethtest/testdata/newpayload.json
vendored
10313
cmd/devp2p/internal/ethtest/testdata/newpayload.json
vendored
File diff suppressed because it is too large
Load diff
2653
cmd/devp2p/internal/ethtest/testdata/txinfo.json
vendored
2653
cmd/devp2p/internal/ethtest/testdata/txinfo.json
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -26,7 +26,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth/protocols/eth"
|
||||
"github.com/ethereum/go-ethereum/internal/utesting"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
// sendTxs sends the given transactions to the node and
|
||||
|
|
@ -52,8 +51,7 @@ func (s *Suite) sendTxs(t *utesting.T, txs []*types.Transaction) error {
|
|||
return fmt.Errorf("peering failed: %v", err)
|
||||
}
|
||||
|
||||
encTxs, _ := rlp.EncodeToRawList(txs)
|
||||
if err = sendConn.Write(ethProto, eth.TransactionsMsg, eth.TransactionsPacket{RawList: encTxs}); err != nil {
|
||||
if err = sendConn.Write(ethProto, eth.TransactionsMsg, eth.TransactionsPacket(txs)); err != nil {
|
||||
return fmt.Errorf("failed to write message to connection: %v", err)
|
||||
}
|
||||
|
||||
|
|
@ -70,8 +68,7 @@ func (s *Suite) sendTxs(t *utesting.T, txs []*types.Transaction) error {
|
|||
}
|
||||
switch msg := msg.(type) {
|
||||
case *eth.TransactionsPacket:
|
||||
txs, _ := msg.Items()
|
||||
for _, tx := range txs {
|
||||
for _, tx := range *msg {
|
||||
got[tx.Hash()] = true
|
||||
}
|
||||
case *eth.NewPooledTransactionHashesPacket:
|
||||
|
|
@ -83,10 +80,9 @@ func (s *Suite) sendTxs(t *utesting.T, txs []*types.Transaction) error {
|
|||
if err != nil {
|
||||
t.Logf("invalid GetBlockHeaders request: %v", err)
|
||||
}
|
||||
encHeaders, _ := rlp.EncodeToRawList(headers)
|
||||
recvConn.Write(ethProto, eth.BlockHeadersMsg, ð.BlockHeadersPacket{
|
||||
RequestId: msg.RequestId,
|
||||
List: encHeaders,
|
||||
RequestId: msg.RequestId,
|
||||
BlockHeadersRequest: headers,
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("unexpected eth wire msg: %s", pretty.Sdump(msg))
|
||||
|
|
@ -171,10 +167,9 @@ func (s *Suite) sendInvalidTxs(t *utesting.T, txs []*types.Transaction) error {
|
|||
if err != nil {
|
||||
t.Logf("invalid GetBlockHeaders request: %v", err)
|
||||
}
|
||||
encHeaders, _ := rlp.EncodeToRawList(headers)
|
||||
recvConn.Write(ethProto, eth.BlockHeadersMsg, ð.BlockHeadersPacket{
|
||||
RequestId: msg.RequestId,
|
||||
List: encHeaders,
|
||||
RequestId: msg.RequestId,
|
||||
BlockHeadersRequest: headers,
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("unexpected eth message: %v", pretty.Sdump(msg))
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ func (s *Suite) AllTests() []utesting.Test {
|
|||
{Name: "Ping", Fn: s.TestPing},
|
||||
{Name: "PingLargeRequestID", Fn: s.TestPingLargeRequestID},
|
||||
{Name: "PingMultiIP", Fn: s.TestPingMultiIP},
|
||||
{Name: "HandshakeResend", Fn: s.TestHandshakeResend},
|
||||
{Name: "PingHandshakeInterrupted", Fn: s.TestPingHandshakeInterrupted},
|
||||
{Name: "TalkRequest", Fn: s.TestTalkRequest},
|
||||
{Name: "FindnodeZeroDistance", Fn: s.TestFindnodeZeroDistance},
|
||||
{Name: "FindnodeResults", Fn: s.TestFindnodeResults},
|
||||
|
|
@ -158,20 +158,22 @@ the attempt from a different IP.`)
|
|||
}
|
||||
}
|
||||
|
||||
// TestHandshakeResend starts a handshake, but doesn't finish it and sends a second ordinary message
|
||||
// packet instead of a handshake message packet. The remote node should repeat the previous WHOAREYOU
|
||||
// challenge for the first PING.
|
||||
func (s *Suite) TestHandshakeResend(t *utesting.T) {
|
||||
// TestPingHandshakeInterrupted starts a handshake, but doesn't finish it and sends a second ordinary message
|
||||
// packet instead of a handshake message packet. The remote node should respond with
|
||||
// another WHOAREYOU challenge for the second packet.
|
||||
func (s *Suite) TestPingHandshakeInterrupted(t *utesting.T) {
|
||||
t.Log(`TestPingHandshakeInterrupted starts a handshake, but doesn't finish it and sends a second ordinary message
|
||||
packet instead of a handshake message packet. The remote node should respond with
|
||||
another WHOAREYOU challenge for the second packet.`)
|
||||
|
||||
conn, l1 := s.listen1(t)
|
||||
defer conn.close()
|
||||
|
||||
// First PING triggers challenge.
|
||||
ping := &v5wire.Ping{ReqID: conn.nextReqID()}
|
||||
conn.write(l1, ping, nil)
|
||||
var challenge1 *v5wire.Whoareyou
|
||||
switch resp := conn.read(l1).(type) {
|
||||
case *v5wire.Whoareyou:
|
||||
challenge1 = resp
|
||||
t.Logf("got WHOAREYOU for PING")
|
||||
default:
|
||||
t.Fatal("expected WHOAREYOU, got", resp)
|
||||
|
|
@ -179,16 +181,9 @@ func (s *Suite) TestHandshakeResend(t *utesting.T) {
|
|||
|
||||
// Send second PING.
|
||||
ping2 := &v5wire.Ping{ReqID: conn.nextReqID()}
|
||||
conn.write(l1, ping2, nil)
|
||||
switch resp := conn.read(l1).(type) {
|
||||
case *v5wire.Whoareyou:
|
||||
if resp.Nonce != challenge1.Nonce {
|
||||
t.Fatalf("wrong nonce %x in WHOAREYOU (want %x)", resp.Nonce[:], challenge1.Nonce[:])
|
||||
}
|
||||
if !bytes.Equal(resp.ChallengeData, challenge1.ChallengeData) {
|
||||
t.Fatalf("wrong ChallengeData in resent WHOAREYOU (want %x)", resp.ChallengeData, challenge1.ChallengeData)
|
||||
}
|
||||
resp.Node = conn.remote
|
||||
switch resp := conn.reqresp(l1, ping2).(type) {
|
||||
case *v5wire.Pong:
|
||||
checkPong(t, resp, ping2, l1)
|
||||
default:
|
||||
t.Fatal("expected WHOAREYOU, got", resp)
|
||||
}
|
||||
|
|
@ -257,50 +252,34 @@ that they are returned by FINDNODE.`)
|
|||
|
||||
// Create bystanders.
|
||||
nodes := make([]*bystander, 5)
|
||||
liveCh := make(chan enode.ID, len(nodes))
|
||||
added := make(chan enode.ID, len(nodes))
|
||||
for i := range nodes {
|
||||
nodes[i] = newBystander(t, s, liveCh)
|
||||
nodes[i] = newBystander(t, s, added)
|
||||
defer nodes[i].close()
|
||||
}
|
||||
|
||||
// Prefill each bystander with the full bystander set so background FINDNODE
|
||||
// lookups see useful routing data instead of empty responses.
|
||||
known := make([]*enode.Node, 0, len(nodes))
|
||||
for _, bn := range nodes {
|
||||
known = append(known, bn.conn.localNode.Node())
|
||||
}
|
||||
for _, bn := range nodes {
|
||||
bn.known = append([]*enode.Node(nil), known...)
|
||||
}
|
||||
|
||||
// Wait until enough bystanders have actually become live, i.e. the remote node
|
||||
// has revalidated them by sending PING and receiving our PONG.
|
||||
requiredLiveNodes := len(nodes)
|
||||
// Get them added to the remote table.
|
||||
timeout := 60 * time.Second
|
||||
timeoutCh := time.After(timeout)
|
||||
liveSet := make(map[enode.ID]*enode.Node)
|
||||
for len(liveSet) < requiredLiveNodes {
|
||||
for count := 0; count < len(nodes); {
|
||||
select {
|
||||
case id := <-liveCh:
|
||||
for _, bn := range nodes {
|
||||
if bn.id() == id {
|
||||
liveSet[id] = bn.conn.localNode.Node()
|
||||
break
|
||||
}
|
||||
}
|
||||
t.Logf("bystander node %v became live", id)
|
||||
case id := <-added:
|
||||
t.Logf("bystander node %v added to remote table", id)
|
||||
count++
|
||||
case <-timeoutCh:
|
||||
t.Errorf("remote revalidated %d bystander nodes in %v, need %d to continue", len(liveSet), timeout, requiredLiveNodes)
|
||||
t.Errorf("remote added %d bystander nodes in %v, need %d to continue", count, timeout, len(nodes))
|
||||
t.Logf("this can happen if the node has a non-empty table from previous runs")
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Logf("continuing after all %d bystander nodes became live", len(liveSet))
|
||||
t.Logf("all %d bystander nodes were added", len(nodes))
|
||||
|
||||
// Collect live nodes by distance.
|
||||
// Collect our nodes by distance.
|
||||
var dists []uint
|
||||
expect := make(map[enode.ID]*enode.Node)
|
||||
for id, n := range liveSet {
|
||||
expect[id] = n
|
||||
for _, bn := range nodes {
|
||||
n := bn.conn.localNode.Node()
|
||||
expect[n.ID()] = n
|
||||
d := uint(enode.LogDist(n.ID(), s.Dest.ID()))
|
||||
if !slices.Contains(dists, d) {
|
||||
dists = append(dists, d)
|
||||
|
|
@ -311,63 +290,42 @@ that they are returned by FINDNODE.`)
|
|||
t.Log("requesting nodes")
|
||||
conn, l1 := s.listen1(t)
|
||||
defer conn.close()
|
||||
|
||||
const maxAttempts = 5
|
||||
const retryInterval = 2 * time.Second
|
||||
|
||||
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
||||
foundNodes, err := conn.findnode(l1, dists)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
missing := make(map[enode.ID]struct{})
|
||||
for id := range expect {
|
||||
missing[id] = struct{}{}
|
||||
}
|
||||
for _, n := range foundNodes {
|
||||
delete(missing, n.ID())
|
||||
}
|
||||
t.Logf("attempt %d: remote returned %d nodes for distance list %v, missing %d", attempt, len(foundNodes), dists, len(missing))
|
||||
if len(missing) == 0 {
|
||||
t.Logf("all %d expected live nodes were returned", len(expect))
|
||||
return
|
||||
}
|
||||
if attempt < maxAttempts {
|
||||
time.Sleep(retryInterval)
|
||||
}
|
||||
foundNodes, err := conn.findnode(l1, dists)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("remote returned %d nodes for distance list %v", len(foundNodes), dists)
|
||||
for _, n := range foundNodes {
|
||||
delete(expect, n.ID())
|
||||
}
|
||||
if len(expect) > 0 {
|
||||
t.Errorf("missing %d nodes in FINDNODE result", len(expect))
|
||||
t.Logf("this can happen if the test is run multiple times in quick succession")
|
||||
t.Logf("and the remote node hasn't removed dead nodes from previous runs yet")
|
||||
} else {
|
||||
t.Logf("all %d expected nodes were returned", len(nodes))
|
||||
}
|
||||
t.Errorf("missing nodes in FINDNODE result after %d attempts", maxAttempts)
|
||||
t.Logf("this can happen if the node has a non-empty table from previous runs")
|
||||
}
|
||||
|
||||
// A bystander is a node whose only purpose is filling a spot in the remote table.
|
||||
type bystander struct {
|
||||
dest *enode.Node
|
||||
conn *conn
|
||||
l net.PacketConn
|
||||
known []*enode.Node
|
||||
dest *enode.Node
|
||||
conn *conn
|
||||
l net.PacketConn
|
||||
|
||||
liveCh chan enode.ID
|
||||
sent map[v5wire.Nonce]v5wire.Packet
|
||||
done sync.WaitGroup
|
||||
addedCh chan enode.ID
|
||||
done sync.WaitGroup
|
||||
}
|
||||
|
||||
func newBystander(t *utesting.T, s *Suite, live chan enode.ID) *bystander {
|
||||
func newBystander(t *utesting.T, s *Suite, added chan enode.ID) *bystander {
|
||||
conn, l := s.listen1(t)
|
||||
conn.setEndpoint(l) // bystander nodes need IP/port to get pinged
|
||||
bn := &bystander{
|
||||
conn: conn,
|
||||
l: l,
|
||||
dest: s.Dest,
|
||||
liveCh: live,
|
||||
sent: make(map[v5wire.Nonce]v5wire.Packet),
|
||||
conn: conn,
|
||||
l: l,
|
||||
dest: s.Dest,
|
||||
addedCh: added,
|
||||
}
|
||||
// Establish an initial session and let the remote learn this node before
|
||||
// switching to the passive responder loop below.
|
||||
conn.reqresp(l, &v5wire.Ping{
|
||||
ReqID: conn.nextReqID(),
|
||||
ENRSeq: conn.localNode.Seq(),
|
||||
})
|
||||
bn.done.Add(1)
|
||||
go bn.loop()
|
||||
return bn
|
||||
|
|
@ -388,57 +346,48 @@ func (bn *bystander) close() {
|
|||
func (bn *bystander) loop() {
|
||||
defer bn.done.Done()
|
||||
|
||||
var (
|
||||
lastPing time.Time
|
||||
wasAdded bool
|
||||
)
|
||||
for {
|
||||
p, from := bn.conn.readFrom(bn.l)
|
||||
switch p := p.(type) {
|
||||
case *v5wire.Whoareyou:
|
||||
p.Node = bn.dest
|
||||
if resp, ok := bn.sent[p.Nonce]; ok {
|
||||
nonce := bn.conn.writeTo(bn.l, resp, p, from)
|
||||
delete(bn.sent, p.Nonce)
|
||||
bn.sent[nonce] = resp
|
||||
} else {
|
||||
bn.conn.writeTo(bn.l, &v5wire.Ping{
|
||||
ReqID: bn.conn.nextReqID(),
|
||||
ENRSeq: bn.conn.localNode.Seq(),
|
||||
}, p, from)
|
||||
}
|
||||
// Ping the remote node.
|
||||
if !wasAdded && time.Since(lastPing) > 10*time.Second {
|
||||
bn.conn.reqresp(bn.l, &v5wire.Ping{
|
||||
ReqID: bn.conn.nextReqID(),
|
||||
ENRSeq: bn.dest.Seq(),
|
||||
})
|
||||
lastPing = time.Now()
|
||||
}
|
||||
// Answer packets.
|
||||
switch p := bn.conn.read(bn.l).(type) {
|
||||
case *v5wire.Ping:
|
||||
resp := &v5wire.Pong{
|
||||
ReqID: append([]byte(nil), p.ReqID...),
|
||||
bn.conn.write(bn.l, &v5wire.Pong{
|
||||
ReqID: p.ReqID,
|
||||
ENRSeq: bn.conn.localNode.Seq(),
|
||||
ToIP: from.IP,
|
||||
ToPort: uint16(from.Port),
|
||||
}
|
||||
nonce := bn.conn.writeTo(bn.l, resp, nil, from)
|
||||
bn.sent[nonce] = resp
|
||||
bn.notifyLive()
|
||||
ToIP: bn.dest.IP(),
|
||||
ToPort: uint16(bn.dest.UDP()),
|
||||
}, nil)
|
||||
wasAdded = true
|
||||
bn.notifyAdded()
|
||||
case *v5wire.Findnode:
|
||||
resp := &v5wire.Nodes{ReqID: append([]byte(nil), p.ReqID...), RespCount: 1}
|
||||
for _, n := range bn.known {
|
||||
if slices.Contains(p.Distances, uint(enode.LogDist(n.ID(), bn.id()))) {
|
||||
resp.Nodes = append(resp.Nodes, n.Record())
|
||||
}
|
||||
}
|
||||
nonce := bn.conn.writeTo(bn.l, resp, nil, from)
|
||||
bn.sent[nonce] = resp
|
||||
bn.conn.write(bn.l, &v5wire.Nodes{ReqID: p.ReqID, RespCount: 1}, nil)
|
||||
wasAdded = true
|
||||
bn.notifyAdded()
|
||||
case *v5wire.TalkRequest:
|
||||
resp := &v5wire.TalkResponse{ReqID: append([]byte(nil), p.ReqID...)}
|
||||
nonce := bn.conn.writeTo(bn.l, resp, nil, from)
|
||||
bn.sent[nonce] = resp
|
||||
bn.conn.write(bn.l, &v5wire.TalkResponse{ReqID: p.ReqID}, nil)
|
||||
case *readError:
|
||||
if netutil.IsTemporaryError(p.err) || v5wire.IsInvalidHeader(p.err) {
|
||||
continue
|
||||
if !netutil.IsTemporaryError(p.err) {
|
||||
bn.conn.logf("shutting down: %v", p.err)
|
||||
return
|
||||
}
|
||||
bn.conn.logf("shutting down: %v", p.err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (bn *bystander) notifyLive() {
|
||||
if bn.liveCh != nil {
|
||||
bn.liveCh <- bn.id()
|
||||
bn.liveCh = nil
|
||||
func (bn *bystander) notifyAdded() {
|
||||
if bn.addedCh != nil {
|
||||
bn.addedCh <- bn.id()
|
||||
bn.addedCh = nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,16 +127,14 @@ func (tc *conn) nextReqID() []byte {
|
|||
// The request is retried if a handshake is requested.
|
||||
func (tc *conn) reqresp(c net.PacketConn, req v5wire.Packet) v5wire.Packet {
|
||||
reqnonce := tc.write(c, req, nil)
|
||||
resp, from := tc.readFrom(c)
|
||||
switch resp := resp.(type) {
|
||||
switch resp := tc.read(c).(type) {
|
||||
case *v5wire.Whoareyou:
|
||||
if resp.Nonce != reqnonce {
|
||||
return readErrorf("wrong nonce %x in WHOAREYOU (want %x)", resp.Nonce[:], reqnonce[:])
|
||||
}
|
||||
resp.Node = tc.remote
|
||||
tc.writeTo(c, req, resp, from)
|
||||
resp2, _ := tc.readFrom(c)
|
||||
return resp2
|
||||
tc.write(c, req, resp)
|
||||
return tc.read(c)
|
||||
default:
|
||||
return resp
|
||||
}
|
||||
|
|
@ -152,24 +150,21 @@ func (tc *conn) findnode(c net.PacketConn, dists []uint) ([]*enode.Node, error)
|
|||
results []*enode.Node
|
||||
)
|
||||
for n := 1; n > 0; {
|
||||
resp, from := tc.readFrom(c)
|
||||
switch resp := resp.(type) {
|
||||
switch resp := tc.read(c).(type) {
|
||||
case *v5wire.Whoareyou:
|
||||
// Handle handshake.
|
||||
if resp.Nonce == reqnonce {
|
||||
resp.Node = tc.remote
|
||||
tc.writeTo(c, findnode, resp, from)
|
||||
tc.write(c, findnode, resp)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unexpected WHOAREYOU (nonce %x), waiting for NODES", resp.Nonce[:])
|
||||
}
|
||||
case *v5wire.Ping:
|
||||
// Handle ping from remote.
|
||||
tc.writeTo(c, &v5wire.Pong{
|
||||
tc.write(c, &v5wire.Pong{
|
||||
ReqID: resp.ReqID,
|
||||
ENRSeq: tc.localNode.Seq(),
|
||||
ToIP: from.IP,
|
||||
ToPort: uint16(from.Port),
|
||||
}, nil, from)
|
||||
}, nil)
|
||||
case *v5wire.Nodes:
|
||||
// Got NODES! Check request ID.
|
||||
if !bytes.Equal(resp.ReqID, findnode.ReqID) {
|
||||
|
|
@ -205,16 +200,11 @@ func (tc *conn) findnode(c net.PacketConn, dists []uint) ([]*enode.Node, error)
|
|||
|
||||
// write sends a packet on the given connection.
|
||||
func (tc *conn) write(c net.PacketConn, p v5wire.Packet, challenge *v5wire.Whoareyou) v5wire.Nonce {
|
||||
return tc.writeTo(c, p, challenge, tc.remoteAddr)
|
||||
}
|
||||
|
||||
// writeTo sends a packet on the given connection to the given UDP address.
|
||||
func (tc *conn) writeTo(c net.PacketConn, p v5wire.Packet, challenge *v5wire.Whoareyou, to *net.UDPAddr) v5wire.Nonce {
|
||||
packet, nonce, err := tc.codec.Encode(tc.remote.ID(), tc.remoteAddr.String(), p, challenge)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("can't encode %v packet: %v", p.Name(), err))
|
||||
}
|
||||
if _, err := c.WriteTo(packet, to); err != nil {
|
||||
if _, err := c.WriteTo(packet, tc.remoteAddr); err != nil {
|
||||
tc.logf("Can't send %s: %v", p.Name(), err)
|
||||
} else {
|
||||
tc.logf(">> %s", p.Name())
|
||||
|
|
@ -224,30 +214,20 @@ func (tc *conn) writeTo(c net.PacketConn, p v5wire.Packet, challenge *v5wire.Who
|
|||
|
||||
// read waits for an incoming packet on the given connection.
|
||||
func (tc *conn) read(c net.PacketConn) v5wire.Packet {
|
||||
p, _ := tc.readFrom(c)
|
||||
return p
|
||||
}
|
||||
|
||||
// readFrom waits for an incoming packet and returns its source address.
|
||||
func (tc *conn) readFrom(c net.PacketConn) (v5wire.Packet, *net.UDPAddr) {
|
||||
buf := make([]byte, 1280)
|
||||
if err := c.SetReadDeadline(time.Now().Add(waitTime)); err != nil {
|
||||
return &readError{err}, nil
|
||||
return &readError{err}
|
||||
}
|
||||
n, from, err := c.ReadFrom(buf)
|
||||
n, fromAddr, err := c.ReadFrom(buf)
|
||||
if err != nil {
|
||||
return &readError{err}, nil
|
||||
return &readError{err}
|
||||
}
|
||||
udpFrom, _ := from.(*net.UDPAddr)
|
||||
// Use tc.remoteAddr for codec/session lookup because the fixture keys sessions
|
||||
// by the advertised endpoint, but return the actual UDP source so responses can
|
||||
// comply with the spec and go back to the request envelope address.
|
||||
_, _, p, err := tc.codec.Decode(buf[:n], tc.remoteAddr.String())
|
||||
_, _, p, err := tc.codec.Decode(buf[:n], fromAddr.String())
|
||||
if err != nil {
|
||||
return &readError{err}, udpFrom
|
||||
return &readError{err}
|
||||
}
|
||||
tc.logf("<< %s", p.Name())
|
||||
return p, udpFrom
|
||||
return p
|
||||
}
|
||||
|
||||
// logf prints to the test log.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
|
@ -31,31 +30,6 @@ import (
|
|||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// decodeRLPxDisconnect parses a disconnect message payload. Per the RLPx spec
|
||||
// the payload is a list containing a single reason, but some implementations
|
||||
// (including older geth) sent the reason as a bare byte. Accept both forms.
|
||||
func decodeRLPxDisconnect(data []byte) (p2p.DiscReason, error) {
|
||||
s := rlp.NewStream(bytes.NewReader(data), uint64(len(data)))
|
||||
k, _, err := s.Kind()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var reason p2p.DiscReason
|
||||
if k == rlp.List {
|
||||
if _, err := s.List(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := s.Decode(&reason); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return reason, nil
|
||||
}
|
||||
if err := s.Decode(&reason); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return reason, nil
|
||||
}
|
||||
|
||||
var (
|
||||
rlpxCommand = &cli.Command{
|
||||
Name: "rlpx",
|
||||
|
|
@ -129,15 +103,11 @@ func rlpxPing(ctx *cli.Context) error {
|
|||
}
|
||||
fmt.Printf("%+v\n", h)
|
||||
case 1:
|
||||
// The disconnect message is specified as a list containing the reason,
|
||||
// but some implementations (including older geth) send the reason as a
|
||||
// single byte. Handle both forms, and on failure include the raw payload
|
||||
// so the operator can see what was actually sent.
|
||||
reason, decErr := decodeRLPxDisconnect(data)
|
||||
if decErr != nil {
|
||||
return fmt.Errorf("invalid disconnect message: %v (raw=0x%x)", decErr, data)
|
||||
var msg []p2p.DiscReason
|
||||
if rlp.DecodeBytes(data, &msg); len(msg) == 0 {
|
||||
return errors.New("invalid disconnect message")
|
||||
}
|
||||
return fmt.Errorf("received disconnect message: %v", reason)
|
||||
return fmt.Errorf("received disconnect message: %v", msg[0])
|
||||
default:
|
||||
return fmt.Errorf("invalid message code %d, expected handshake (code zero) or disconnect (code one)", code)
|
||||
}
|
||||
|
|
@ -173,6 +143,9 @@ type testParams struct {
|
|||
|
||||
func cliTestParams(ctx *cli.Context) *testParams {
|
||||
nodeStr := ctx.String(testNodeFlag.Name)
|
||||
if nodeStr == "" {
|
||||
exit(fmt.Errorf("missing -%s", testNodeFlag.Name))
|
||||
}
|
||||
node, err := parseNode(nodeStr)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
|
|
@ -183,5 +156,14 @@ func cliTestParams(ctx *cli.Context) *testParams {
|
|||
jwt: ctx.String(testNodeJWTFlag.Name),
|
||||
chainDir: ctx.String(testChainDirFlag.Name),
|
||||
}
|
||||
if p.engineAPI == "" {
|
||||
exit(fmt.Errorf("missing -%s", testNodeEngineFlag.Name))
|
||||
}
|
||||
if p.jwt == "" {
|
||||
exit(fmt.Errorf("missing -%s", testNodeJWTFlag.Name))
|
||||
}
|
||||
if p.chainDir == "" {
|
||||
exit(fmt.Errorf("missing -%s", testChainDirFlag.Name))
|
||||
}
|
||||
return &p
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
// Copyright 2026 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 (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
)
|
||||
|
||||
func TestDecodeRLPxDisconnect(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
payload []byte
|
||||
want p2p.DiscReason
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "list form (spec-compliant)",
|
||||
payload: []byte{0xc1, 0x04}, // [4] = TooManyPeers
|
||||
want: p2p.DiscTooManyPeers,
|
||||
},
|
||||
{
|
||||
name: "list form with reason zero",
|
||||
payload: []byte{0xc1, 0x80}, // [0] = Requested
|
||||
want: p2p.DiscRequested,
|
||||
},
|
||||
{
|
||||
name: "bare byte form (legacy geth)",
|
||||
payload: []byte{0x04}, // 4 = TooManyPeers
|
||||
want: p2p.DiscTooManyPeers,
|
||||
},
|
||||
{
|
||||
name: "bare byte form zero",
|
||||
payload: []byte{0x80}, // 0 = Requested
|
||||
want: p2p.DiscRequested,
|
||||
},
|
||||
{
|
||||
name: "empty payload",
|
||||
payload: []byte{},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got, err := decodeRLPxDisconnect(tc.payload)
|
||||
if tc.wantErr {
|
||||
if err == nil {
|
||||
t.Fatalf("expected error, got reason=%v", got)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if got != tc.want {
|
||||
t.Fatalf("got reason %v, want %v", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -39,29 +39,26 @@ var (
|
|||
}
|
||||
|
||||
// for eth/snap tests
|
||||
testChainDirFlag = &cli.PathFlag{
|
||||
testChainDirFlag = &cli.StringFlag{
|
||||
Name: "chain",
|
||||
Usage: "Test chain directory (required)",
|
||||
Category: flags.TestingCategory,
|
||||
Required: true,
|
||||
}
|
||||
testNodeFlag = &cli.StringFlag{
|
||||
Name: "node",
|
||||
Usage: "Peer-to-Peer endpoint (ENR) of the test node (required)",
|
||||
Category: flags.TestingCategory,
|
||||
Required: true,
|
||||
}
|
||||
testNodeJWTFlag = &cli.StringFlag{
|
||||
Name: "jwtsecret",
|
||||
Usage: "JWT secret for the engine API of the test node (required)",
|
||||
Category: flags.TestingCategory,
|
||||
Required: true,
|
||||
Value: "0x7365637265747365637265747365637265747365637265747365637265747365",
|
||||
}
|
||||
testNodeEngineFlag = &cli.StringFlag{
|
||||
Name: "engineapi",
|
||||
Usage: "Engine API endpoint of the test node (required)",
|
||||
Category: flags.TestingCategory,
|
||||
Required: true,
|
||||
}
|
||||
|
||||
// These two are specific to the discovery tests.
|
||||
|
|
|
|||
131
cmd/era/main.go
131
cmd/era/main.go
|
|
@ -30,8 +30,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/internal/era"
|
||||
"github.com/ethereum/go-ethereum/internal/era/execdb"
|
||||
"github.com/ethereum/go-ethereum/internal/era/onedb"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/internal/flags"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
|
|
@ -55,7 +53,7 @@ var (
|
|||
eraSizeFlag = &cli.IntFlag{
|
||||
Name: "size",
|
||||
Usage: "number of blocks per era",
|
||||
Value: era.MaxSize,
|
||||
Value: era.MaxEra1Size,
|
||||
}
|
||||
txsFlag = &cli.BoolFlag{
|
||||
Name: "txs",
|
||||
|
|
@ -133,7 +131,7 @@ func block(ctx *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// info prints some high-level information about the era file.
|
||||
// info prints some high-level information about the era1 file.
|
||||
func info(ctx *cli.Context) error {
|
||||
epoch, err := strconv.ParseUint(ctx.Args().First(), 10, 64)
|
||||
if err != nil {
|
||||
|
|
@ -144,34 +142,33 @@ func info(ctx *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
defer e.Close()
|
||||
var (
|
||||
accHex string
|
||||
tdStr string
|
||||
)
|
||||
if acc, err := e.Accumulator(); err == nil {
|
||||
accHex = acc.Hex()
|
||||
acc, err := e.Accumulator()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading accumulator: %w", err)
|
||||
}
|
||||
if td, err := e.InitialTD(); err == nil {
|
||||
tdStr = td.String()
|
||||
td, err := e.InitialTD()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading total difficulty: %w", err)
|
||||
}
|
||||
info := struct {
|
||||
Accumulator string `json:"accumulator,omitempty"`
|
||||
TotalDifficulty string `json:"totalDifficulty,omitempty"`
|
||||
StartBlock uint64 `json:"startBlock"`
|
||||
Count uint64 `json:"count"`
|
||||
Accumulator common.Hash `json:"accumulator"`
|
||||
TotalDifficulty *big.Int `json:"totalDifficulty"`
|
||||
StartBlock uint64 `json:"startBlock"`
|
||||
Count uint64 `json:"count"`
|
||||
}{
|
||||
accHex, tdStr, e.Start(), e.Count(),
|
||||
acc, td, e.Start(), e.Count(),
|
||||
}
|
||||
b, _ := json.MarshalIndent(info, "", " ")
|
||||
fmt.Println(string(b))
|
||||
return nil
|
||||
}
|
||||
|
||||
// open opens an era file at a certain epoch.
|
||||
func open(ctx *cli.Context, epoch uint64) (era.Era, error) {
|
||||
dir := ctx.String(dirFlag.Name)
|
||||
network := ctx.String(networkFlag.Name)
|
||||
|
||||
// open opens an era1 file at a certain epoch.
|
||||
func open(ctx *cli.Context, epoch uint64) (*era.Era, error) {
|
||||
var (
|
||||
dir = ctx.String(dirFlag.Name)
|
||||
network = ctx.String(networkFlag.Name)
|
||||
)
|
||||
entries, err := era.ReadDir(dir, network)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading era dir: %w", err)
|
||||
|
|
@ -179,28 +176,7 @@ func open(ctx *cli.Context, epoch uint64) (era.Era, error) {
|
|||
if epoch >= uint64(len(entries)) {
|
||||
return nil, fmt.Errorf("epoch out-of-bounds: last %d, want %d", len(entries)-1, epoch)
|
||||
}
|
||||
path := filepath.Join(dir, entries[epoch])
|
||||
return openByPath(path)
|
||||
}
|
||||
|
||||
// openByPath tries to open a single file as either eraE or era1 based on extension,
|
||||
// falling back to the other reader if needed.
|
||||
func openByPath(path string) (era.Era, error) {
|
||||
switch strings.ToLower(filepath.Ext(path)) {
|
||||
case ".erae":
|
||||
if e, err := execdb.Open(path); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return e, nil
|
||||
}
|
||||
case ".era1":
|
||||
if e, err := onedb.Open(path); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return e, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported or unreadable era file: %s", path)
|
||||
return era.Open(filepath.Join(dir, entries[epoch]))
|
||||
}
|
||||
|
||||
// verify checks each era1 file in a directory to ensure it is well-formed and
|
||||
|
|
@ -227,58 +203,18 @@ func verify(ctx *cli.Context) error {
|
|||
return fmt.Errorf("error reading %s: %w", dir, err)
|
||||
}
|
||||
|
||||
// Build the verification list respecting the rule:
|
||||
// era1: must have accumulator, always verify
|
||||
// erae: verify only if accumulator exists (pre-merge)
|
||||
|
||||
// Build list of files to verify.
|
||||
verify := make([]string, 0, len(entries))
|
||||
|
||||
for _, name := range entries {
|
||||
path := filepath.Join(dir, name)
|
||||
ext := strings.ToLower(filepath.Ext(name))
|
||||
|
||||
switch ext {
|
||||
case ".era1":
|
||||
e, err := onedb.Open(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error opening era1 file %s: %w", name, err)
|
||||
}
|
||||
_, accErr := e.Accumulator()
|
||||
e.Close()
|
||||
if accErr != nil {
|
||||
return fmt.Errorf("era1 file %s missing accumulator: %w", name, accErr)
|
||||
}
|
||||
verify = append(verify, path)
|
||||
|
||||
case ".erae":
|
||||
e, err := execdb.Open(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error opening erae file %s: %w", name, err)
|
||||
}
|
||||
_, accErr := e.Accumulator()
|
||||
e.Close()
|
||||
if accErr == nil {
|
||||
verify = append(verify, path) // pre-merge only
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unsupported era file: %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
if len(verify) != len(roots) {
|
||||
return fmt.Errorf("mismatch between eras to verify (%d) and provided roots (%d)", len(verify), len(roots))
|
||||
if len(entries) != len(roots) {
|
||||
return errors.New("number of era1 files should match the number of accumulator hashes")
|
||||
}
|
||||
|
||||
// Verify each epoch matches the expected root.
|
||||
for i, want := range roots {
|
||||
// Wrap in function so defers don't stack.
|
||||
err := func() error {
|
||||
path := verify[i]
|
||||
name := filepath.Base(path)
|
||||
e, err := openByPath(path)
|
||||
name := entries[i]
|
||||
e, err := era.Open(filepath.Join(dir, name))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error opening era file %s: %w", name, err)
|
||||
return fmt.Errorf("error opening era1 file %s: %w", name, err)
|
||||
}
|
||||
defer e.Close()
|
||||
// Read accumulator and check against expected.
|
||||
|
|
@ -307,7 +243,7 @@ func verify(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
// checkAccumulator verifies the accumulator matches the data in the Era.
|
||||
func checkAccumulator(e era.Era) error {
|
||||
func checkAccumulator(e *era.Era) error {
|
||||
var (
|
||||
err error
|
||||
want common.Hash
|
||||
|
|
@ -321,7 +257,7 @@ func checkAccumulator(e era.Era) error {
|
|||
if td, err = e.InitialTD(); err != nil {
|
||||
return fmt.Errorf("error reading total difficulty: %w", err)
|
||||
}
|
||||
it, err := e.Iterator()
|
||||
it, err := era.NewIterator(e)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error making era iterator: %w", err)
|
||||
}
|
||||
|
|
@ -337,6 +273,9 @@ func checkAccumulator(e era.Era) error {
|
|||
// accumulation across the entire set and are verified at the end.
|
||||
for it.Next() {
|
||||
// 1) next() walks the block index, so we're able to implicitly verify it.
|
||||
if it.Error() != nil {
|
||||
return fmt.Errorf("error reading block %d: %w", it.Number(), it.Error())
|
||||
}
|
||||
block, receipts, err := it.BlockAndReceipts()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading block %d: %w", it.Number(), err)
|
||||
|
|
@ -351,13 +290,9 @@ func checkAccumulator(e era.Era) error {
|
|||
if rr != block.ReceiptHash() {
|
||||
return fmt.Errorf("receipt root in block %d mismatch: want %s, got %s", block.NumberU64(), block.ReceiptHash(), rr)
|
||||
}
|
||||
// Only include pre-merge blocks in accumulator calculation.
|
||||
// Post-merge blocks have difficulty == 0.
|
||||
if block.Difficulty().Sign() > 0 {
|
||||
hashes = append(hashes, block.Hash())
|
||||
td.Add(td, block.Difficulty())
|
||||
tds = append(tds, new(big.Int).Set(td))
|
||||
}
|
||||
hashes = append(hashes, block.Hash())
|
||||
td.Add(td, block.Difficulty())
|
||||
tds = append(tds, new(big.Int).Set(td))
|
||||
}
|
||||
if it.Error() != nil {
|
||||
return fmt.Errorf("error reading block %d: %w", it.Number(), it.Error())
|
||||
|
|
|
|||
|
|
@ -17,18 +17,16 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"os"
|
||||
"regexp"
|
||||
"slices"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/tests"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
|
@ -36,52 +34,33 @@ import (
|
|||
var blockTestCommand = &cli.Command{
|
||||
Action: blockTestCmd,
|
||||
Name: "blocktest",
|
||||
Usage: "Executes the given blockchain tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).",
|
||||
Usage: "Executes the given blockchain tests",
|
||||
ArgsUsage: "<path>",
|
||||
Flags: slices.Concat([]cli.Flag{
|
||||
DumpFlag,
|
||||
HumanReadableFlag,
|
||||
RunFlag,
|
||||
WitnessCrossCheckFlag,
|
||||
FuzzFlag,
|
||||
}, traceFlags),
|
||||
}
|
||||
|
||||
func blockTestCmd(ctx *cli.Context) error {
|
||||
path := ctx.Args().First()
|
||||
|
||||
// If path is provided, run the tests at that path.
|
||||
if len(path) != 0 {
|
||||
var (
|
||||
collected = collectFiles(path)
|
||||
results []testResult
|
||||
)
|
||||
for _, fname := range collected {
|
||||
r, err := runBlockTest(ctx, fname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
results = append(results, r...)
|
||||
}
|
||||
report(ctx, results)
|
||||
return nil
|
||||
if len(path) == 0 {
|
||||
return errors.New("path argument required")
|
||||
}
|
||||
// Otherwise, read filenames from stdin and execute back-to-back.
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
fname := scanner.Text()
|
||||
if len(fname) == 0 {
|
||||
return nil
|
||||
}
|
||||
results, err := runBlockTest(ctx, fname)
|
||||
var (
|
||||
collected = collectFiles(path)
|
||||
results []testResult
|
||||
)
|
||||
for _, fname := range collected {
|
||||
r, err := runBlockTest(ctx, fname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// During fuzzing, we report the result after every block
|
||||
if !ctx.IsSet(FuzzFlag.Name) {
|
||||
report(ctx, results)
|
||||
}
|
||||
results = append(results, r...)
|
||||
}
|
||||
report(ctx, results)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -100,11 +79,6 @@ func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
|
|||
}
|
||||
tracer := tracerFromFlags(ctx)
|
||||
|
||||
// Suppress INFO logs during fuzzing
|
||||
if ctx.IsSet(FuzzFlag.Name) {
|
||||
log.SetDefault(log.NewLogger(log.DiscardHandler()))
|
||||
}
|
||||
|
||||
// Pull out keys to sort and ensure tests are run in order.
|
||||
keys := slices.Sorted(maps.Keys(tests))
|
||||
|
||||
|
|
@ -114,35 +88,16 @@ func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
|
|||
if !re.MatchString(name) {
|
||||
continue
|
||||
}
|
||||
test := tests[name]
|
||||
result := &testResult{Name: name, Pass: true}
|
||||
var finalRoot *common.Hash
|
||||
if err := test.Run(false, rawdb.PathScheme, ctx.Bool(WitnessCrossCheckFlag.Name), tracer, func(res error, chain *core.BlockChain) {
|
||||
if err := tests[name].Run(false, rawdb.PathScheme, ctx.Bool(WitnessCrossCheckFlag.Name), tracer, func(res error, chain *core.BlockChain) {
|
||||
if ctx.Bool(DumpFlag.Name) {
|
||||
if s, _ := chain.State(); s != nil {
|
||||
result.State = dump(s)
|
||||
}
|
||||
}
|
||||
// Capture final state root for end marker
|
||||
if chain != nil {
|
||||
root := chain.CurrentBlock().Root
|
||||
finalRoot = &root
|
||||
}
|
||||
}); err != nil {
|
||||
result.Pass, result.Error = false, err.Error()
|
||||
}
|
||||
|
||||
// Always assign fork (regardless of pass/fail or tracer)
|
||||
result.Fork = test.Network()
|
||||
// Assign root if test succeeded
|
||||
if result.Pass && finalRoot != nil {
|
||||
result.Root = finalRoot
|
||||
}
|
||||
|
||||
// When fuzzing, write results after every block
|
||||
if ctx.IsSet(FuzzFlag.Name) {
|
||||
report(ctx, []testResult{*result})
|
||||
}
|
||||
results = append(results, *result)
|
||||
}
|
||||
return results, nil
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ type header struct {
|
|||
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
SlotNumber *uint64 `json:"slotNumber" rlp:"optional"`
|
||||
}
|
||||
|
||||
type headerMarshaling struct {
|
||||
|
|
@ -69,7 +68,6 @@ type headerMarshaling struct {
|
|||
BaseFee *math.HexOrDecimal256
|
||||
BlobGasUsed *math.HexOrDecimal64
|
||||
ExcessBlobGas *math.HexOrDecimal64
|
||||
SlotNumber *math.HexOrDecimal64
|
||||
}
|
||||
|
||||
type bbInput struct {
|
||||
|
|
@ -138,7 +136,6 @@ func (i *bbInput) ToBlock() *types.Block {
|
|||
BlobGasUsed: i.Header.BlobGasUsed,
|
||||
ExcessBlobGas: i.Header.ExcessBlobGas,
|
||||
ParentBeaconRoot: i.Header.ParentBeaconBlockRoot,
|
||||
SlotNumber: i.Header.SlotNumber,
|
||||
}
|
||||
|
||||
// Fill optional values.
|
||||
|
|
|
|||
|
|
@ -17,11 +17,8 @@
|
|||
package t8ntool
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
stdmath "math"
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
|
@ -35,7 +32,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto/keccak"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
|
|
@ -43,15 +39,12 @@ import (
|
|||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/holiman/uint256"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
type Prestate struct {
|
||||
Env stEnv `json:"env"`
|
||||
Pre types.GenesisAlloc `json:"pre"`
|
||||
TreeLeaves map[common.Hash]hexutil.Bytes `json:"vkt,omitempty"`
|
||||
// AllocPath, when non-empty, causes Apply to stream the alloc from disk
|
||||
// instead of reading Pre, so the full map never materializes in memory.
|
||||
AllocPath string `json:"-"`
|
||||
Env stEnv `json:"env"`
|
||||
Pre types.GenesisAlloc `json:"pre"`
|
||||
}
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type ExecutionResult -field-override executionResultMarshaling -out gen_execresult.go
|
||||
|
|
@ -107,7 +100,6 @@ type stEnv struct {
|
|||
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
|
||||
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *uint64 `json:"slotNumber"`
|
||||
}
|
||||
|
||||
type stEnvMarshaling struct {
|
||||
|
|
@ -126,7 +118,6 @@ type stEnvMarshaling struct {
|
|||
ExcessBlobGas *math.HexOrDecimal64
|
||||
ParentExcessBlobGas *math.HexOrDecimal64
|
||||
ParentBlobGasUsed *math.HexOrDecimal64
|
||||
SlotNumber *math.HexOrDecimal64
|
||||
}
|
||||
|
||||
type rejectedTx struct {
|
||||
|
|
@ -151,27 +142,17 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
return h
|
||||
}
|
||||
var (
|
||||
isEIP4762 = chainConfig.IsUBT(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp)
|
||||
statedb *state.StateDB
|
||||
)
|
||||
if pre.AllocPath != "" {
|
||||
var err error
|
||||
statedb, err = MakePreStateStreaming(rawdb.NewMemoryDatabase(), pre.AllocPath, isEIP4762)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
} else {
|
||||
statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre, isEIP4762)
|
||||
}
|
||||
var (
|
||||
statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre)
|
||||
signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp)
|
||||
gaspool = core.NewGasPool(pre.Env.GasLimit)
|
||||
gaspool = new(core.GasPool)
|
||||
blockHash = common.Hash{0x13, 0x37}
|
||||
rejectedTxs []*rejectedTx
|
||||
includedTxs types.Transactions
|
||||
gasUsed = uint64(0)
|
||||
blobGasUsed = uint64(0)
|
||||
receipts = make(types.Receipts, 0)
|
||||
)
|
||||
gaspool.AddGas(pre.Env.GasLimit)
|
||||
vmContext := vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
|
|
@ -211,7 +192,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
ExcessBlobGas: pre.Env.ParentExcessBlobGas,
|
||||
BlobGasUsed: pre.Env.ParentBlobGasUsed,
|
||||
BaseFee: pre.Env.ParentBaseFee,
|
||||
SlotNumber: pre.Env.SlotNumber,
|
||||
}
|
||||
header := &types.Header{
|
||||
Time: pre.Env.Timestamp,
|
||||
|
|
@ -272,19 +252,16 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
statedb.SetTxContext(tx.Hash(), len(receipts))
|
||||
var (
|
||||
snapshot = statedb.Snapshot()
|
||||
gp = gaspool.Snapshot()
|
||||
prevGas = gaspool.Gas()
|
||||
)
|
||||
receipt, err := core.ApplyTransactionWithEVM(msg, gaspool, statedb, vmContext.BlockNumber, blockHash, pre.Env.Timestamp, tx, evm)
|
||||
receipt, err := core.ApplyTransactionWithEVM(msg, gaspool, statedb, vmContext.BlockNumber, blockHash, pre.Env.Timestamp, tx, &gasUsed, evm)
|
||||
if err != nil {
|
||||
statedb.RevertToSnapshot(snapshot)
|
||||
log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From, "error", err)
|
||||
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
|
||||
gaspool.Set(gp)
|
||||
gaspool.SetGas(prevGas)
|
||||
continue
|
||||
}
|
||||
if receipt.Logs == nil {
|
||||
receipt.Logs = []*types.Log{}
|
||||
}
|
||||
includedTxs = append(includedTxs, tx)
|
||||
if hashError != nil {
|
||||
return nil, nil, nil, NewError(ErrorMissingBlockhash, hashError)
|
||||
|
|
@ -324,10 +301,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
// Amount is in gwei, turn into wei
|
||||
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
|
||||
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)
|
||||
|
||||
if isEIP4762 {
|
||||
statedb.AccessEvents().AddAccount(w.Address, true, stdmath.MaxUint64)
|
||||
}
|
||||
}
|
||||
|
||||
// Gather the execution-layer triggered requests.
|
||||
|
|
@ -366,7 +339,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
Receipts: receipts,
|
||||
Rejected: rejectedTxs,
|
||||
Difficulty: (*math.HexOrDecimal256)(vmContext.Difficulty),
|
||||
GasUsed: (math.HexOrDecimal64)(gaspool.Used()),
|
||||
GasUsed: (math.HexOrDecimal64)(gasUsed),
|
||||
BaseFee: (*math.HexOrDecimal256)(vmContext.BaseFee),
|
||||
}
|
||||
if pre.Env.Withdrawals != nil {
|
||||
|
|
@ -381,10 +354,15 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
// Set requestsHash on block.
|
||||
h := types.CalcRequestsHash(requests)
|
||||
execRs.RequestsHash = &h
|
||||
for i := range requests {
|
||||
// remove prefix
|
||||
requests[i] = requests[i][1:]
|
||||
}
|
||||
execRs.Requests = requests
|
||||
}
|
||||
|
||||
// Re-create statedb instance with new root for MPT mode
|
||||
// Re-create statedb instance with new root upon the updated database
|
||||
// for accessing latest states.
|
||||
statedb, err = state.New(root, statedb.Database())
|
||||
if err != nil {
|
||||
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not reopen state: %v", err))
|
||||
|
|
@ -393,17 +371,12 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
return statedb, execRs, body, nil
|
||||
}
|
||||
|
||||
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, isBintrie bool) *state.StateDB {
|
||||
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true, IsUBT: isBintrie})
|
||||
func MakePreState(db ethdb.Database, accounts types.GenesisAlloc) *state.StateDB {
|
||||
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true})
|
||||
sdb := state.NewDatabase(tdb, nil)
|
||||
|
||||
root := types.EmptyRootHash
|
||||
if isBintrie {
|
||||
root = types.EmptyBinaryHash
|
||||
}
|
||||
statedb, err := state.New(root, sdb)
|
||||
statedb, err := state.New(types.EmptyRootHash, sdb)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to create initial statedb: %v", err))
|
||||
panic(fmt.Errorf("failed to create initial state: %v", err))
|
||||
}
|
||||
for addr, a := range accounts {
|
||||
statedb.SetCode(addr, a.Code, tracing.CodeChangeUnspecified)
|
||||
|
|
@ -414,15 +387,10 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, isBintrie bool
|
|||
}
|
||||
}
|
||||
// Commit and re-open to start with a clean state.
|
||||
root, err = statedb.Commit(0, false, false)
|
||||
root, err := statedb.Commit(0, false, false)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to commit initial state: %v", err))
|
||||
}
|
||||
// If bintrie mode started, check if conversion happened
|
||||
if isBintrie {
|
||||
return statedb
|
||||
}
|
||||
// For MPT mode, reopen the state with the committed root
|
||||
statedb, err = state.New(root, sdb)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to reopen state after commit: %v", err))
|
||||
|
|
@ -430,78 +398,8 @@ func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, isBintrie bool
|
|||
return statedb
|
||||
}
|
||||
|
||||
// MakePreStateStreaming is like MakePreState, but decodes the alloc from disk
|
||||
// one account at a time so the full map is never held in memory.
|
||||
func MakePreStateStreaming(db ethdb.Database, allocPath string, isBintrie bool) (*state.StateDB, error) {
|
||||
tdb := triedb.NewDatabase(db, &triedb.Config{Preimages: true, IsUBT: isBintrie})
|
||||
sdb := state.NewDatabase(tdb, nil)
|
||||
|
||||
root := types.EmptyRootHash
|
||||
if isBintrie {
|
||||
root = types.EmptyBinaryHash
|
||||
}
|
||||
statedb, err := state.New(root, sdb)
|
||||
if err != nil {
|
||||
return nil, NewError(ErrorEVM, fmt.Errorf("failed to create initial statedb: %v", err))
|
||||
}
|
||||
|
||||
f, err := os.Open(allocPath)
|
||||
if err != nil {
|
||||
return nil, NewError(ErrorIO, fmt.Errorf("failed reading alloc file: %v", err))
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
dec := json.NewDecoder(f)
|
||||
tok, err := dec.Token()
|
||||
if err != nil {
|
||||
return nil, NewError(ErrorJson, fmt.Errorf("failed reading alloc opening token: %v", err))
|
||||
}
|
||||
if d, ok := tok.(json.Delim); !ok || d != '{' {
|
||||
return nil, NewError(ErrorJson, fmt.Errorf("expected alloc object, got %v", tok))
|
||||
}
|
||||
for dec.More() {
|
||||
keyTok, err := dec.Token()
|
||||
if err != nil {
|
||||
return nil, NewError(ErrorJson, fmt.Errorf("failed reading alloc key: %v", err))
|
||||
}
|
||||
keyStr, ok := keyTok.(string)
|
||||
if !ok {
|
||||
return nil, NewError(ErrorJson, fmt.Errorf("alloc key not a string: %v", keyTok))
|
||||
}
|
||||
addr := common.HexToAddress(keyStr)
|
||||
var acct types.Account
|
||||
if err := dec.Decode(&acct); err != nil {
|
||||
return nil, NewError(ErrorJson, fmt.Errorf("failed decoding account %s: %v", keyStr, err))
|
||||
}
|
||||
statedb.SetCode(addr, acct.Code, tracing.CodeChangeUnspecified)
|
||||
statedb.SetNonce(addr, acct.Nonce, tracing.NonceChangeGenesis)
|
||||
if acct.Balance != nil {
|
||||
statedb.SetBalance(addr, uint256.MustFromBig(acct.Balance), tracing.BalanceIncreaseGenesisBalance)
|
||||
}
|
||||
for k, v := range acct.Storage {
|
||||
statedb.SetState(addr, k, v)
|
||||
}
|
||||
}
|
||||
if _, err := dec.Token(); err != nil {
|
||||
return nil, NewError(ErrorJson, fmt.Errorf("failed reading alloc closing token: %v", err))
|
||||
}
|
||||
|
||||
root, err = statedb.Commit(0, false, false)
|
||||
if err != nil {
|
||||
return nil, NewError(ErrorEVM, fmt.Errorf("failed to commit initial state: %v", err))
|
||||
}
|
||||
if isBintrie {
|
||||
return statedb, nil
|
||||
}
|
||||
statedb, err = state.New(root, sdb)
|
||||
if err != nil {
|
||||
return nil, NewError(ErrorEVM, fmt.Errorf("failed to reopen state after commit: %v", err))
|
||||
}
|
||||
return statedb, nil
|
||||
}
|
||||
|
||||
func rlpHash(x any) (h common.Hash) {
|
||||
hw := keccak.NewLegacyKeccak256()
|
||||
func rlpHash(x interface{}) (h common.Hash) {
|
||||
hw := sha3.NewLegacyKeccak256()
|
||||
rlp.Encode(hw, x)
|
||||
hw.Sum(h[:0])
|
||||
return h
|
||||
|
|
|
|||
|
|
@ -56,35 +56,27 @@ func (l *fileWritingTracer) Write(p []byte) (n int, err error) {
|
|||
return n, nil
|
||||
}
|
||||
|
||||
// newFileWriter creates a tracer which wraps inner hooks (typically a logger),
|
||||
// newFileWriter creates a set of hooks which wraps inner hooks (typically a logger),
|
||||
// and writes the output to a file, one file per transaction.
|
||||
func newFileWriter(baseDir string, innerFn func(out io.Writer) *tracing.Hooks) *tracers.Tracer {
|
||||
func newFileWriter(baseDir string, innerFn func(out io.Writer) *tracing.Hooks) *tracing.Hooks {
|
||||
t := &fileWritingTracer{
|
||||
baseDir: baseDir,
|
||||
suffix: "jsonl",
|
||||
}
|
||||
t.inner = innerFn(t) // instantiate the inner tracer
|
||||
return &tracers.Tracer{
|
||||
Hooks: t.hooks(),
|
||||
GetResult: func() (json.RawMessage, error) { return json.RawMessage("{}"), nil },
|
||||
Stop: func(err error) {},
|
||||
}
|
||||
return t.hooks()
|
||||
}
|
||||
|
||||
// newResultWriter creates a tracer that wraps and invokes an underlying tracer,
|
||||
// newResultWriter creates a set of hooks wraps and invokes an underlying tracer,
|
||||
// and writes the result (getResult-output) to file, one per transaction.
|
||||
func newResultWriter(baseDir string, tracer *tracers.Tracer) *tracers.Tracer {
|
||||
func newResultWriter(baseDir string, tracer *tracers.Tracer) *tracing.Hooks {
|
||||
t := &fileWritingTracer{
|
||||
baseDir: baseDir,
|
||||
getResult: tracer.GetResult,
|
||||
inner: tracer.Hooks,
|
||||
suffix: "json",
|
||||
}
|
||||
return &tracers.Tracer{
|
||||
Hooks: t.hooks(),
|
||||
GetResult: func() (json.RawMessage, error) { return json.RawMessage("{}"), nil },
|
||||
Stop: func(err error) {},
|
||||
}
|
||||
return t.hooks()
|
||||
}
|
||||
|
||||
// OnTxStart creates a new output-file specific for this transaction, and invokes
|
||||
|
|
|
|||
|
|
@ -88,14 +88,6 @@ var (
|
|||
"\t<file> - into the file <file> ",
|
||||
Value: "block.json",
|
||||
}
|
||||
OutputBTFlag = &cli.StringFlag{
|
||||
Name: "output.vkt",
|
||||
Usage: "Determines where to put the `BT` of the post-state.\n" +
|
||||
"\t`stdout` - into the stdout output\n" +
|
||||
"\t`stderr` - into the stderr output\n" +
|
||||
"\t<file> - into the file <file> ",
|
||||
Value: "vkt.json",
|
||||
}
|
||||
InputAllocFlag = &cli.StringFlag{
|
||||
Name: "input.alloc",
|
||||
Usage: "`stdin` or file name of where to find the prestate alloc to use.",
|
||||
|
|
@ -131,11 +123,6 @@ var (
|
|||
Usage: "`stdin` or file name of where to find the transactions list in RLP form.",
|
||||
Value: "txs.rlp",
|
||||
}
|
||||
// TODO(@CPerezz): rename `Name` of the file in a follow-up PR (relays on EEST -> https://github.com/ethereum/execution-spec-tests/tree/verkle/main)
|
||||
InputBTFlag = &cli.StringFlag{
|
||||
Name: "input.vkt",
|
||||
Usage: "`stdin` or file name of where to find the prestate BT.",
|
||||
}
|
||||
SealCliqueFlag = &cli.StringFlag{
|
||||
Name: "seal.clique",
|
||||
Usage: "Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.",
|
||||
|
|
@ -162,11 +149,6 @@ var (
|
|||
strings.Join(vm.ActivateableEips(), ", ")),
|
||||
Value: "GrayGlacier",
|
||||
}
|
||||
OpcodeCountFlag = &cli.StringFlag{
|
||||
Name: "opcode.count",
|
||||
Usage: "If set, opcode execution counts will be written to this file (relative to output.basedir).",
|
||||
Value: "",
|
||||
}
|
||||
VerbosityFlag = &cli.IntFlag{
|
||||
Name: "verbosity",
|
||||
Usage: "sets the verbosity level",
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ func (h header) MarshalJSON() ([]byte, error) {
|
|||
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
|
||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
SlotNumber *math.HexOrDecimal64 `json:"slotNumber" rlp:"optional"`
|
||||
}
|
||||
var enc header
|
||||
enc.ParentHash = h.ParentHash
|
||||
|
|
@ -61,7 +60,6 @@ func (h header) MarshalJSON() ([]byte, error) {
|
|||
enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed)
|
||||
enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas)
|
||||
enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot
|
||||
enc.SlotNumber = (*math.HexOrDecimal64)(h.SlotNumber)
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +86,6 @@ func (h *header) UnmarshalJSON(input []byte) error {
|
|||
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
|
||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
SlotNumber *math.HexOrDecimal64 `json:"slotNumber" rlp:"optional"`
|
||||
}
|
||||
var dec header
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -158,8 +155,5 @@ func (h *header) UnmarshalJSON(input []byte) error {
|
|||
if dec.ParentBeaconBlockRoot != nil {
|
||||
h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
||||
}
|
||||
if dec.SlotNumber != nil {
|
||||
h.SlotNumber = (*uint64)(dec.SlotNumber)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
|||
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
||||
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *math.HexOrDecimal64 `json:"slotNumber"`
|
||||
}
|
||||
var enc stEnv
|
||||
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
||||
|
|
@ -60,7 +59,6 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
|||
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
|
||||
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
|
||||
enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot
|
||||
enc.SlotNumber = (*math.HexOrDecimal64)(s.SlotNumber)
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +85,6 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
|||
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
||||
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||
SlotNumber *math.HexOrDecimal64 `json:"slotNumber"`
|
||||
}
|
||||
var dec stEnv
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -157,8 +154,5 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
|||
if dec.ParentBeaconBlockRoot != nil {
|
||||
s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
||||
}
|
||||
if dec.SlotNumber != nil {
|
||||
s.SlotNumber = (*uint64)(dec.SlotNumber)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
|
||||
"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/rlp"
|
||||
"github.com/ethereum/go-ethereum/tests"
|
||||
|
|
@ -117,6 +115,9 @@ func Transaction(ctx *cli.Context) error {
|
|||
}
|
||||
var results []result
|
||||
for it.Next() {
|
||||
if err := it.Err(); err != nil {
|
||||
return NewError(ErrorIO, err)
|
||||
}
|
||||
var tx types.Transaction
|
||||
err := rlp.DecodeBytes(it.Value(), &tx)
|
||||
if err != nil {
|
||||
|
|
@ -133,21 +134,21 @@ func Transaction(ctx *cli.Context) error {
|
|||
}
|
||||
// Check intrinsic gas
|
||||
rules := chainConfig.Rules(common.Big0, true, 0)
|
||||
cost, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai)
|
||||
gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
results = append(results, r)
|
||||
continue
|
||||
}
|
||||
r.IntrinsicGas = cost.RegularGas
|
||||
if tx.Gas() < cost.RegularGas {
|
||||
r.Error = fmt.Errorf("%w: have %d, want %d", core.ErrIntrinsicGas, tx.Gas(), cost.RegularGas)
|
||||
r.IntrinsicGas = gas
|
||||
if tx.Gas() < gas {
|
||||
r.Error = fmt.Errorf("%w: have %d, want %d", core.ErrIntrinsicGas, tx.Gas(), gas)
|
||||
results = append(results, r)
|
||||
continue
|
||||
}
|
||||
// For Prague txs, validate the floor data gas.
|
||||
if rules.IsPrague {
|
||||
floorDataGas, err := core.FloorDataGas(rules, tx.Data())
|
||||
floorDataGas, err := core.FloorDataGas(tx.Data())
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
results = append(results, r)
|
||||
|
|
@ -179,23 +180,14 @@ func Transaction(ctx *cli.Context) error {
|
|||
r.Error = errors.New("gas * maxFeePerGas exceeds 256 bits")
|
||||
}
|
||||
// Check whether the init code size has been exceeded.
|
||||
if tx.To() == nil {
|
||||
if err := vm.CheckMaxInitCodeSize(&rules, uint64(len(tx.Data()))); err != nil {
|
||||
r.Error = err
|
||||
}
|
||||
if chainConfig.IsShanghai(new(big.Int), 0) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize {
|
||||
r.Error = errors.New("max initcode size exceeded")
|
||||
}
|
||||
|
||||
isOsaka := chainConfig.IsOsaka(new(big.Int), 0)
|
||||
isAmsterdam := chainConfig.IsAmsterdam(new(big.Int), 0)
|
||||
if isOsaka && !isAmsterdam && tx.Gas() > params.MaxTxGas {
|
||||
if chainConfig.IsOsaka(new(big.Int), 0) && tx.Gas() > params.MaxTxGas {
|
||||
r.Error = errors.New("gas limit exceeds maximum")
|
||||
}
|
||||
results = append(results, r)
|
||||
}
|
||||
if err := it.Err(); err != nil {
|
||||
return NewError(ErrorIO, err)
|
||||
}
|
||||
|
||||
out, err := json.MarshalIndent(results, "", " ")
|
||||
fmt.Println(string(out))
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package t8ntool
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -29,23 +28,15 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"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/eth/tracers"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/native"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/tests"
|
||||
"github.com/ethereum/go-ethereum/trie/bintrie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/database"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
|
@ -84,11 +75,10 @@ var (
|
|||
)
|
||||
|
||||
type input struct {
|
||||
Alloc types.GenesisAlloc `json:"alloc,omitempty"`
|
||||
Env *stEnv `json:"env,omitempty"`
|
||||
BT map[common.Hash]hexutil.Bytes `json:"vkt,omitempty"`
|
||||
Txs []*txWithKey `json:"txs,omitempty"`
|
||||
TxRlp string `json:"txsRlp,omitempty"`
|
||||
Alloc types.GenesisAlloc `json:"alloc,omitempty"`
|
||||
Env *stEnv `json:"env,omitempty"`
|
||||
Txs []*txWithKey `json:"txs,omitempty"`
|
||||
TxRlp string `json:"txsRlp,omitempty"`
|
||||
}
|
||||
|
||||
func Transition(ctx *cli.Context) error {
|
||||
|
|
@ -100,33 +90,27 @@ func Transition(ctx *cli.Context) error {
|
|||
// stdin input or in files.
|
||||
// Check if anything needs to be read from stdin
|
||||
var (
|
||||
prestate Prestate
|
||||
txIt txIterator // txs to apply
|
||||
allocStr = ctx.String(InputAllocFlag.Name)
|
||||
btStr = ctx.String(InputBTFlag.Name)
|
||||
prestate Prestate
|
||||
txIt txIterator // txs to apply
|
||||
allocStr = ctx.String(InputAllocFlag.Name)
|
||||
|
||||
envStr = ctx.String(InputEnvFlag.Name)
|
||||
txStr = ctx.String(InputTxsFlag.Name)
|
||||
inputData = &input{}
|
||||
)
|
||||
// Figure out the prestate alloc
|
||||
if allocStr == stdinSelector || btStr == stdinSelector || envStr == stdinSelector || txStr == stdinSelector {
|
||||
if allocStr == stdinSelector || envStr == stdinSelector || txStr == stdinSelector {
|
||||
decoder := json.NewDecoder(os.Stdin)
|
||||
if err := decoder.Decode(inputData); err != nil {
|
||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshalling stdin: %v", err))
|
||||
}
|
||||
}
|
||||
if allocStr != stdinSelector {
|
||||
prestate.AllocPath = allocStr
|
||||
} else {
|
||||
prestate.Pre = inputData.Alloc
|
||||
}
|
||||
|
||||
if btStr != stdinSelector && btStr != "" {
|
||||
if err := readFile(btStr, "BT", &inputData.BT); err != nil {
|
||||
if err := readFile(allocStr, "alloc", &inputData.Alloc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
prestate.TreeLeaves = inputData.BT
|
||||
prestate.Pre = inputData.Alloc
|
||||
|
||||
// Set the block environment
|
||||
if envStr != stdinSelector {
|
||||
|
|
@ -168,15 +152,14 @@ func Transition(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
// Configure tracer
|
||||
var tracer *tracers.Tracer
|
||||
if ctx.IsSet(TraceTracerFlag.Name) { // Custom tracing
|
||||
config := json.RawMessage(ctx.String(TraceTracerConfigFlag.Name))
|
||||
innerTracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name),
|
||||
tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name),
|
||||
nil, config, chainConfig)
|
||||
if err != nil {
|
||||
return NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %v", err))
|
||||
}
|
||||
tracer = newResultWriter(baseDir, innerTracer)
|
||||
vmConfig.Tracer = newResultWriter(baseDir, tracer)
|
||||
} else if ctx.Bool(TraceFlag.Name) { // JSON opcode tracing
|
||||
logConfig := &logger.Config{
|
||||
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
|
||||
|
|
@ -184,96 +167,24 @@ func Transition(ctx *cli.Context) error {
|
|||
EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name),
|
||||
}
|
||||
if ctx.Bool(TraceEnableCallFramesFlag.Name) {
|
||||
tracer = newFileWriter(baseDir, func(out io.Writer) *tracing.Hooks {
|
||||
vmConfig.Tracer = newFileWriter(baseDir, func(out io.Writer) *tracing.Hooks {
|
||||
return logger.NewJSONLoggerWithCallFrames(logConfig, out)
|
||||
})
|
||||
} else {
|
||||
tracer = newFileWriter(baseDir, func(out io.Writer) *tracing.Hooks {
|
||||
vmConfig.Tracer = newFileWriter(baseDir, func(out io.Writer) *tracing.Hooks {
|
||||
return logger.NewJSONLogger(logConfig, out)
|
||||
})
|
||||
}
|
||||
}
|
||||
// Configure opcode counter
|
||||
var opcodeTracer *tracers.Tracer
|
||||
if ctx.IsSet(OpcodeCountFlag.Name) && ctx.String(OpcodeCountFlag.Name) != "" {
|
||||
opcodeTracer = native.NewOpcodeCounter()
|
||||
if tracer != nil {
|
||||
// If we have an existing tracer, multiplex with the opcode tracer
|
||||
mux, _ := native.NewMuxTracer([]string{"trace", "opcode"}, []*tracers.Tracer{tracer, opcodeTracer})
|
||||
vmConfig.Tracer = mux.Hooks
|
||||
} else {
|
||||
vmConfig.Tracer = opcodeTracer.Hooks
|
||||
}
|
||||
} else if tracer != nil {
|
||||
vmConfig.Tracer = tracer.Hooks
|
||||
}
|
||||
// Run the test and aggregate the result
|
||||
s, result, body, err := prestate.Apply(vmConfig, chainConfig, txIt, ctx.Int64(RewardFlag.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Write opcode counts if enabled
|
||||
if opcodeTracer != nil {
|
||||
fname := ctx.String(OpcodeCountFlag.Name)
|
||||
result, err := opcodeTracer.GetResult()
|
||||
if err != nil {
|
||||
return NewError(ErrorJson, fmt.Errorf("failed getting opcode counts: %v", err))
|
||||
}
|
||||
if err := saveFile(baseDir, fname, result); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Dump the execution result.
|
||||
var (
|
||||
collector Alloc
|
||||
btleaves map[common.Hash]hexutil.Bytes
|
||||
)
|
||||
isBinary := chainConfig.IsUBT(big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp)
|
||||
allocOutput := ctx.String(OutputAllocFlag.Name)
|
||||
switch {
|
||||
case !isBinary && allocOutput != "" && allocOutput != "stdout" && allocOutput != "stderr":
|
||||
// Stream directly to the output file to avoid materializing the
|
||||
// whole post-state in memory. dispatchOutput is told to skip alloc
|
||||
// by clearing the output name.
|
||||
if err := writeStreamedAlloc(filepath.Join(baseDir, allocOutput), s); err != nil {
|
||||
return err
|
||||
}
|
||||
allocOutput = ""
|
||||
case !isBinary:
|
||||
collector = make(Alloc)
|
||||
s.DumpToCollector(collector, nil)
|
||||
default:
|
||||
btleaves = make(map[common.Hash]hexutil.Bytes)
|
||||
if err := s.DumpBinTrieLeaves(btleaves); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return dispatchOutput(ctx, baseDir, result, collector, allocOutput, body, btleaves)
|
||||
}
|
||||
|
||||
// writeStreamedAlloc writes the post-state alloc to path one account at a
|
||||
// time, producing the same JSON shape as saveFile on an Alloc map.
|
||||
func writeStreamedAlloc(path string, s *state.StateDB) error {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return NewError(ErrorIO, fmt.Errorf("failed creating alloc output file: %v", err))
|
||||
}
|
||||
bw := bufio.NewWriter(f)
|
||||
sa := newStreamingAlloc(bw)
|
||||
s.DumpToCollector(sa, nil)
|
||||
if err := sa.Close(); err != nil {
|
||||
f.Close()
|
||||
return NewError(ErrorIO, fmt.Errorf("failed writing alloc output: %v", err))
|
||||
}
|
||||
if err := bw.Flush(); err != nil {
|
||||
f.Close()
|
||||
return NewError(ErrorIO, fmt.Errorf("failed flushing alloc output: %v", err))
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return NewError(ErrorIO, fmt.Errorf("failed closing alloc output file: %v", err))
|
||||
}
|
||||
log.Info("Wrote file", "file", path)
|
||||
return nil
|
||||
// Dump the execution result
|
||||
collector := make(Alloc)
|
||||
s.DumpToCollector(collector, nil)
|
||||
return dispatchOutput(ctx, baseDir, result, collector, body)
|
||||
}
|
||||
|
||||
func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||
|
|
@ -362,10 +273,6 @@ func (g Alloc) OnAccount(addr *common.Address, dumpAccount state.DumpAccount) {
|
|||
if addr == nil {
|
||||
return
|
||||
}
|
||||
g[*addr] = dumpAccountToTypesAccount(dumpAccount)
|
||||
}
|
||||
|
||||
func dumpAccountToTypesAccount(dumpAccount state.DumpAccount) types.Account {
|
||||
balance, _ := new(big.Int).SetString(dumpAccount.Balance, 0)
|
||||
var storage map[common.Hash]common.Hash
|
||||
if dumpAccount.Storage != nil {
|
||||
|
|
@ -374,64 +281,13 @@ func dumpAccountToTypesAccount(dumpAccount state.DumpAccount) types.Account {
|
|||
storage[k] = common.HexToHash(v)
|
||||
}
|
||||
}
|
||||
return types.Account{
|
||||
genesisAccount := types.Account{
|
||||
Code: dumpAccount.Code,
|
||||
Storage: storage,
|
||||
Balance: balance,
|
||||
Nonce: dumpAccount.Nonce,
|
||||
}
|
||||
}
|
||||
|
||||
// streamingAlloc is a DumpCollector that writes each account to w as it is
|
||||
// visited, emitting a single JSON object keyed by address. Close must be
|
||||
// called to emit the closing brace.
|
||||
type streamingAlloc struct {
|
||||
w io.Writer
|
||||
wroteOne bool
|
||||
err error
|
||||
}
|
||||
|
||||
func newStreamingAlloc(w io.Writer) *streamingAlloc {
|
||||
return &streamingAlloc{w: w}
|
||||
}
|
||||
|
||||
func (s *streamingAlloc) write(b []byte) {
|
||||
if s.err != nil {
|
||||
return
|
||||
}
|
||||
_, s.err = s.w.Write(b)
|
||||
}
|
||||
|
||||
func (s *streamingAlloc) OnRoot(common.Hash) {
|
||||
s.write([]byte{'{'})
|
||||
}
|
||||
|
||||
func (s *streamingAlloc) OnAccount(addr *common.Address, dumpAccount state.DumpAccount) {
|
||||
if s.err != nil || addr == nil {
|
||||
return
|
||||
}
|
||||
keyJSON, err := json.Marshal(*addr)
|
||||
if err != nil {
|
||||
s.err = err
|
||||
return
|
||||
}
|
||||
valueJSON, err := json.Marshal(dumpAccountToTypesAccount(dumpAccount))
|
||||
if err != nil {
|
||||
s.err = err
|
||||
return
|
||||
}
|
||||
if s.wroteOne {
|
||||
s.write([]byte{','})
|
||||
}
|
||||
s.write(keyJSON)
|
||||
s.write([]byte{':'})
|
||||
s.write(valueJSON)
|
||||
s.wroteOne = true
|
||||
}
|
||||
|
||||
func (s *streamingAlloc) Close() error {
|
||||
s.write([]byte{'}'})
|
||||
return s.err
|
||||
g[*addr] = genesisAccount
|
||||
}
|
||||
|
||||
// saveFile marshals the object to the given file
|
||||
|
|
@ -449,9 +305,8 @@ func saveFile(baseDir, filename string, data interface{}) error {
|
|||
}
|
||||
|
||||
// dispatchOutput writes the output data to either stderr or stdout, or to the specified
|
||||
// files. An empty allocOutput skips the alloc dispatch, which is used when the
|
||||
// alloc has already been streamed to disk by the caller.
|
||||
func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, alloc Alloc, allocOutput string, body hexutil.Bytes, bt map[common.Hash]hexutil.Bytes) error {
|
||||
// files
|
||||
func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, alloc Alloc, body hexutil.Bytes) error {
|
||||
stdOutObject := make(map[string]interface{})
|
||||
stdErrObject := make(map[string]interface{})
|
||||
dispatch := func(baseDir, fName, name string, obj interface{}) error {
|
||||
|
|
@ -469,7 +324,7 @@ func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, a
|
|||
}
|
||||
return nil
|
||||
}
|
||||
if err := dispatch(baseDir, allocOutput, "alloc", alloc); err != nil {
|
||||
if err := dispatch(baseDir, ctx.String(OutputAllocFlag.Name), "alloc", alloc); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dispatch(baseDir, ctx.String(OutputResultFlag.Name), "result", result); err != nil {
|
||||
|
|
@ -478,13 +333,6 @@ func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, a
|
|||
if err := dispatch(baseDir, ctx.String(OutputBodyFlag.Name), "body", body); err != nil {
|
||||
return err
|
||||
}
|
||||
// Only write bt output if we actually have binary trie leaves
|
||||
if bt != nil {
|
||||
if err := dispatch(baseDir, ctx.String(OutputBTFlag.Name), "vkt", bt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(stdOutObject) > 0 {
|
||||
b, err := json.MarshalIndent(stdOutObject, "", " ")
|
||||
if err != nil {
|
||||
|
|
@ -503,168 +351,3 @@ func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, a
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BinKey computes the tree key given an address and an optional slot number.
|
||||
func BinKey(ctx *cli.Context) error {
|
||||
if ctx.Args().Len() == 0 || ctx.Args().Len() > 2 {
|
||||
return errors.New("invalid number of arguments: expecting an address and an optional slot number")
|
||||
}
|
||||
|
||||
addr, err := hexutil.Decode(ctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding address: %w", err)
|
||||
}
|
||||
|
||||
if ctx.Args().Len() == 2 {
|
||||
slot, err := hexutil.Decode(ctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding slot: %w", err)
|
||||
}
|
||||
fmt.Printf("%#x\n", bintrie.GetBinaryTreeKeyStorageSlot(common.BytesToAddress(addr), slot))
|
||||
} else {
|
||||
fmt.Printf("%#x\n", bintrie.GetBinaryTreeKeyBasicData(common.BytesToAddress(addr)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BinKeys computes a set of tree keys given a genesis alloc.
|
||||
func BinKeys(ctx *cli.Context) error {
|
||||
var allocStr = ctx.String(InputAllocFlag.Name)
|
||||
var alloc core.GenesisAlloc
|
||||
// Figure out the prestate alloc
|
||||
if allocStr == stdinSelector {
|
||||
decoder := json.NewDecoder(os.Stdin)
|
||||
if err := decoder.Decode(&alloc); err != nil {
|
||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err))
|
||||
}
|
||||
}
|
||||
if allocStr != stdinSelector {
|
||||
if err := readFile(allocStr, "alloc", &alloc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
db := triedb.NewDatabase(rawdb.NewMemoryDatabase(), triedb.UBTDefaults)
|
||||
defer db.Close()
|
||||
|
||||
bt, err := genBinTrieFromAlloc(alloc, db, triedb.UBTDefaults.BinTrieGroupDepth)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating bt: %w", err)
|
||||
}
|
||||
|
||||
collector := make(map[common.Hash]hexutil.Bytes)
|
||||
it, err := bt.NodeIterator(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for it.Next(true) {
|
||||
if it.Leaf() {
|
||||
collector[common.BytesToHash(it.LeafKey())] = it.LeafBlob()
|
||||
}
|
||||
}
|
||||
|
||||
output, err := json.MarshalIndent(collector, "", "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error outputting tree: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println(string(output))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BinTrieRoot computes the root of a Binary Trie from a genesis alloc.
|
||||
func BinTrieRoot(ctx *cli.Context) error {
|
||||
var allocStr = ctx.String(InputAllocFlag.Name)
|
||||
var alloc core.GenesisAlloc
|
||||
if allocStr == stdinSelector {
|
||||
decoder := json.NewDecoder(os.Stdin)
|
||||
if err := decoder.Decode(&alloc); err != nil {
|
||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err))
|
||||
}
|
||||
}
|
||||
if allocStr != stdinSelector {
|
||||
if err := readFile(allocStr, "alloc", &alloc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
db := triedb.NewDatabase(rawdb.NewMemoryDatabase(), triedb.UBTDefaults)
|
||||
defer db.Close()
|
||||
|
||||
bt, err := genBinTrieFromAlloc(alloc, db, triedb.UBTDefaults.BinTrieGroupDepth)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating bt: %w", err)
|
||||
}
|
||||
fmt.Println(bt.Hash().Hex())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(@CPerezz): Should this go to `bintrie` module?
|
||||
func genBinTrieFromAlloc(alloc core.GenesisAlloc, db database.NodeDatabase, groupDepth int) (*bintrie.BinaryTrie, error) {
|
||||
bt, err := bintrie.NewBinaryTrie(types.EmptyBinaryHash, db, groupDepth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for addr, acc := range alloc {
|
||||
for slot, value := range acc.Storage {
|
||||
err := bt.UpdateStorage(addr, slot.Bytes(), value.Big().Bytes())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error inserting storage: %w", err)
|
||||
}
|
||||
}
|
||||
account := &types.StateAccount{
|
||||
Balance: uint256.MustFromBig(acc.Balance),
|
||||
Nonce: acc.Nonce,
|
||||
CodeHash: crypto.Keccak256Hash(acc.Code).Bytes(),
|
||||
Root: common.Hash{},
|
||||
}
|
||||
err := bt.UpdateAccount(addr, account, len(acc.Code))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error inserting account: %w", err)
|
||||
}
|
||||
err = bt.UpdateContractCode(addr, common.BytesToHash(account.CodeHash), acc.Code)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error inserting code: %w", err)
|
||||
}
|
||||
}
|
||||
return bt, nil
|
||||
}
|
||||
|
||||
// BinaryCodeChunkKey computes the tree key of a code-chunk for a given address.
|
||||
func BinaryCodeChunkKey(ctx *cli.Context) error {
|
||||
if ctx.Args().Len() == 0 || ctx.Args().Len() > 2 {
|
||||
return errors.New("invalid number of arguments: expecting an address and an code-chunk number")
|
||||
}
|
||||
|
||||
addr, err := hexutil.Decode(ctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding address: %w", err)
|
||||
}
|
||||
chunkNumberBytes, err := hexutil.Decode(ctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding chunk number: %w", err)
|
||||
}
|
||||
var chunkNumber uint256.Int
|
||||
chunkNumber.SetBytes(chunkNumberBytes)
|
||||
|
||||
fmt.Printf("%#x\n", bintrie.GetBinaryTreeKeyCodeChunk(common.BytesToAddress(addr), &chunkNumber))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BinaryCodeChunkCode returns the code chunkification for a given code.
|
||||
func BinaryCodeChunkCode(ctx *cli.Context) error {
|
||||
if ctx.Args().Len() == 0 || ctx.Args().Len() > 1 {
|
||||
return errors.New("invalid number of arguments: expecting a bytecode")
|
||||
}
|
||||
|
||||
bytecode, err := hexutil.Decode(ctx.Args().Get(0))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding address: %w", err)
|
||||
}
|
||||
|
||||
chunkedCode := bintrie.ChunkifyCode(bytecode)
|
||||
fmt.Printf("%#x\n", chunkedCode)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,11 +55,6 @@ var (
|
|||
Usage: "benchmark the execution",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
FuzzFlag = &cli.BoolFlag{
|
||||
Name: "fuzz",
|
||||
Usage: "adapts output format for fuzzing",
|
||||
Category: flags.VMCategory,
|
||||
}
|
||||
WitnessCrossCheckFlag = &cli.BoolFlag{
|
||||
Name: "cross-check",
|
||||
Aliases: []string{"xc"},
|
||||
|
|
@ -115,7 +110,7 @@ var (
|
|||
Name: "trace.noreturndata",
|
||||
Aliases: []string{"noreturndata"},
|
||||
Value: true,
|
||||
Usage: "disable return data output",
|
||||
Usage: "enable return data output",
|
||||
Category: traceCategory,
|
||||
}
|
||||
|
||||
|
|
@ -151,64 +146,16 @@ var (
|
|||
t8ntool.TraceEnableCallFramesFlag,
|
||||
t8ntool.OutputBasedir,
|
||||
t8ntool.OutputAllocFlag,
|
||||
t8ntool.OutputBTFlag,
|
||||
t8ntool.OutputResultFlag,
|
||||
t8ntool.OutputBodyFlag,
|
||||
t8ntool.InputAllocFlag,
|
||||
t8ntool.InputEnvFlag,
|
||||
t8ntool.InputBTFlag,
|
||||
t8ntool.InputTxsFlag,
|
||||
t8ntool.ForknameFlag,
|
||||
t8ntool.ChainIDFlag,
|
||||
t8ntool.RewardFlag,
|
||||
t8ntool.OpcodeCountFlag,
|
||||
},
|
||||
}
|
||||
|
||||
verkleCommand = &cli.Command{
|
||||
Name: "verkle",
|
||||
Aliases: []string{"vkt"},
|
||||
Usage: "Binary Trie helpers",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "tree-keys",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "compute a set of binary trie keys, given their source addresses and optional slot numbers",
|
||||
Action: t8ntool.BinKeys,
|
||||
Flags: []cli.Flag{
|
||||
t8ntool.InputAllocFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "single-key",
|
||||
Aliases: []string{"vk"},
|
||||
Usage: "compute the binary trie key given an address and optional slot number",
|
||||
Action: t8ntool.BinKey,
|
||||
},
|
||||
{
|
||||
Name: "code-chunk-key",
|
||||
Aliases: []string{"vck"},
|
||||
Usage: "compute the binary trie key given an address and chunk number",
|
||||
Action: t8ntool.BinaryCodeChunkKey,
|
||||
},
|
||||
{
|
||||
Name: "chunkify-code",
|
||||
Aliases: []string{"vcc"},
|
||||
Usage: "chunkify a given bytecode for a binary trie",
|
||||
Action: t8ntool.BinaryCodeChunkCode,
|
||||
},
|
||||
{
|
||||
Name: "state-root",
|
||||
Aliases: []string{"vsr"},
|
||||
Usage: "compute the state-root of a binary trie for the given alloc",
|
||||
Action: t8ntool.BinTrieRoot,
|
||||
Flags: []cli.Flag{
|
||||
t8ntool.InputAllocFlag,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
transactionCommand = &cli.Command{
|
||||
Name: "transaction",
|
||||
Aliases: []string{"t9n"},
|
||||
|
|
@ -263,7 +210,6 @@ func init() {
|
|||
stateTransitionCommand,
|
||||
transactionCommand,
|
||||
blockBuilderCommand,
|
||||
verkleCommand,
|
||||
}
|
||||
app.Before = func(ctx *cli.Context) error {
|
||||
flags.MigrateGlobalFlags(ctx)
|
||||
|
|
|
|||
|
|
@ -166,11 +166,8 @@ func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) ([]byte, exe
|
|||
if haveGasUsed != gasUsed {
|
||||
panic(fmt.Sprintf("gas differs, have %v want %v", haveGasUsed, gasUsed))
|
||||
}
|
||||
if (haveErr == nil) != (err == nil) {
|
||||
panic(fmt.Sprintf("err differs in nil-ness, have %v want %v", haveErr, err))
|
||||
}
|
||||
if haveErr != nil && err != nil && haveErr.Error() != err.Error() {
|
||||
panic(fmt.Sprintf("err differs, have %q want %q", haveErr.Error(), err.Error()))
|
||||
if haveErr != err {
|
||||
panic(fmt.Sprintf("err differs, have %v want %v", haveErr, err))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
2
cmd/evm/testdata/1/exp.json
vendored
2
cmd/evm/testdata/1/exp.json
vendored
|
|
@ -24,7 +24,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x5208",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x0557bacce3375c98d806609b8d5043072f0b6a8bae45ae5a67a00d3a1a18d673",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
|
|
|
|||
4
cmd/evm/testdata/13/exp2.json
vendored
4
cmd/evm/testdata/13/exp2.json
vendored
|
|
@ -12,7 +12,7 @@
|
|||
"status": "0x0",
|
||||
"cumulativeGasUsed": "0x84d0",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x84d0",
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
"status": "0x0",
|
||||
"cumulativeGasUsed": "0x109a0",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x84d0",
|
||||
|
|
|
|||
2
cmd/evm/testdata/23/exp.json
vendored
2
cmd/evm/testdata/23/exp.json
vendored
|
|
@ -11,7 +11,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x520b",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x520b",
|
||||
|
|
|
|||
4
cmd/evm/testdata/24/exp.json
vendored
4
cmd/evm/testdata/24/exp.json
vendored
|
|
@ -27,7 +27,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0xa861",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x92ea4a28224d033afb20e0cc2b290d4c7c2d61f6a4800a680e4e19ac962ee941",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0xa861",
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x10306",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x16b1d912f1d664f3f60f4e1b5f296f3c82a64a1a253117b4851d18bc03c4f1da",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5aa5",
|
||||
|
|
|
|||
2
cmd/evm/testdata/25/exp.json
vendored
2
cmd/evm/testdata/25/exp.json
vendored
|
|
@ -23,7 +23,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x5208",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x92ea4a28224d033afb20e0cc2b290d4c7c2d61f6a4800a680e4e19ac962ee941",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
|
|
|
|||
2
cmd/evm/testdata/28/exp.json
vendored
2
cmd/evm/testdata/28/exp.json
vendored
|
|
@ -28,7 +28,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0xa865",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x7508d7139d002a4b3a26a4f12dec0d87cb46075c78bf77a38b569a133b509262",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0xa865",
|
||||
|
|
|
|||
2
cmd/evm/testdata/29/exp.json
vendored
2
cmd/evm/testdata/29/exp.json
vendored
|
|
@ -26,7 +26,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x5208",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x84f70aba406a55628a0620f26d260f90aeb6ccc55fed6ec2ac13dd4f727032ed",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
|
|
|
|||
2
cmd/evm/testdata/3/exp.json
vendored
2
cmd/evm/testdata/3/exp.json
vendored
|
|
@ -24,7 +24,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x521f",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x521f",
|
||||
|
|
|
|||
4
cmd/evm/testdata/30/exp.json
vendored
4
cmd/evm/testdata/30/exp.json
vendored
|
|
@ -25,7 +25,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x5208",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0xa410",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"logs": [],
|
||||
"logs": null,
|
||||
"transactionHash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x5208",
|
||||
|
|
|
|||
2
cmd/evm/testdata/33/exp.json
vendored
2
cmd/evm/testdata/33/exp.json
vendored
|
|
@ -44,7 +44,7 @@
|
|||
"root": "0x",
|
||||
"status": "0x1",
|
||||
"cumulativeGasUsed": "0x15fa9",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","logs": [],"transactionHash": "0x0417aab7c1d8a3989190c3167c132876ce9b8afd99262c5a0f9d06802de3d7ef",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","logs": null,"transactionHash": "0x0417aab7c1d8a3989190c3167c132876ce9b8afd99262c5a0f9d06802de3d7ef",
|
||||
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||
"gasUsed": "0x15fa9",
|
||||
"effectiveGasPrice": null,
|
||||
|
|
|
|||
|
|
@ -1,177 +0,0 @@
|
|||
// Copyright 2026 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/>.
|
||||
|
||||
// fetchpayload queries an Ethereum node over RPC, fetches a block and its
|
||||
// execution witness, and writes the combined Payload (ChainID + Block +
|
||||
// Witness) to disk in the format consumed by cmd/keeper.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/stateless"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
// Payload is duplicated from cmd/keeper/main.go (package main, not importable).
|
||||
type Payload struct {
|
||||
ChainID uint64
|
||||
Block *types.Block
|
||||
Witness *stateless.Witness
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
rpcURL = flag.String("rpc", "http://localhost:8545", "RPC endpoint URL")
|
||||
blockArg = flag.String("block", "latest", `Block number: decimal, 0x-hex, or "latest"`)
|
||||
format = flag.String("format", "rlp", "Comma-separated output formats: rlp, hex, json")
|
||||
outDir = flag.String("out", "", "Output directory (default: current directory)")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Parse block number (nil means "latest" in ethclient).
|
||||
blockNum, err := parseBlockNumber(*blockArg)
|
||||
if err != nil {
|
||||
fatal("invalid block number %q: %v", *blockArg, err)
|
||||
}
|
||||
|
||||
// Connect to the node.
|
||||
client, err := ethclient.DialContext(ctx, *rpcURL)
|
||||
if err != nil {
|
||||
fatal("failed to connect to %s: %v", *rpcURL, err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
chainID, err := client.ChainID(ctx)
|
||||
if err != nil {
|
||||
fatal("failed to get chain ID: %v", err)
|
||||
}
|
||||
|
||||
// Fetch the block first so we have a concrete number for the witness call,
|
||||
// avoiding a race where "latest" advances between the two RPCs.
|
||||
block, err := client.BlockByNumber(ctx, blockNum)
|
||||
if err != nil {
|
||||
fatal("failed to fetch block: %v", err)
|
||||
}
|
||||
fmt.Printf("Fetched block %d (%#x)\n", block.NumberU64(), block.Hash())
|
||||
|
||||
// Fetch the execution witness via the debug namespace.
|
||||
var extWitness stateless.ExtWitness
|
||||
err = client.Client().CallContext(ctx, &extWitness, "debug_executionWitness", rpc.BlockNumber(block.NumberU64()))
|
||||
if err != nil {
|
||||
fatal("failed to fetch execution witness: %v", err)
|
||||
}
|
||||
|
||||
witness := new(stateless.Witness)
|
||||
err = witness.FromExtWitness(&extWitness)
|
||||
if err != nil {
|
||||
fatal("failed to convert witness: %v", err)
|
||||
}
|
||||
|
||||
payload := Payload{
|
||||
ChainID: chainID.Uint64(),
|
||||
Block: block,
|
||||
Witness: witness,
|
||||
}
|
||||
|
||||
// Encode payload as RLP (shared by "rlp" and "hex" formats).
|
||||
rlpBytes, err := rlp.EncodeToBytes(payload)
|
||||
if err != nil {
|
||||
fatal("failed to RLP-encode payload: %v", err)
|
||||
}
|
||||
|
||||
// Write one output file per requested format.
|
||||
blockHex := fmt.Sprintf("%x", block.NumberU64())
|
||||
for f := range strings.SplitSeq(*format, ",") {
|
||||
f = strings.TrimSpace(f)
|
||||
outPath := filepath.Join(*outDir, fmt.Sprintf("%s_payload.%s", blockHex, f))
|
||||
|
||||
var data []byte
|
||||
switch f {
|
||||
case "rlp":
|
||||
data = rlpBytes
|
||||
case "hex":
|
||||
data = []byte(hexutil.Encode(rlpBytes))
|
||||
case "json":
|
||||
data, err = marshalJSONPayload(chainID, block, &extWitness)
|
||||
if err != nil {
|
||||
fatal("failed to JSON-encode payload: %v", err)
|
||||
}
|
||||
default:
|
||||
fatal("unknown format %q (valid: rlp, hex, json)", f)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(outPath, data, 0644); err != nil {
|
||||
fatal("failed to write %s: %v", outPath, err)
|
||||
}
|
||||
fmt.Printf("Wrote %s (%d bytes)\n", outPath, len(data))
|
||||
}
|
||||
}
|
||||
|
||||
// parseBlockNumber converts a CLI string to *big.Int.
|
||||
// Returns nil for "latest" (ethclient convention for the head block).
|
||||
func parseBlockNumber(s string) (*big.Int, error) {
|
||||
if strings.EqualFold(s, "latest") {
|
||||
return nil, nil
|
||||
}
|
||||
n := new(big.Int)
|
||||
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
|
||||
if _, ok := n.SetString(s[2:], 16); !ok {
|
||||
return nil, fmt.Errorf("invalid hex number")
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
if _, ok := n.SetString(s, 10); !ok {
|
||||
return nil, fmt.Errorf("invalid decimal number")
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// jsonPayload is a JSON-friendly representation of Payload. It uses ExtWitness
|
||||
// instead of the internal Witness (which has no JSON marshaling).
|
||||
type jsonPayload struct {
|
||||
ChainID uint64 `json:"chainId"`
|
||||
Block *types.Block `json:"block"`
|
||||
Witness *stateless.ExtWitness `json:"witness"`
|
||||
}
|
||||
|
||||
func marshalJSONPayload(chainID *big.Int, block *types.Block, ext *stateless.ExtWitness) ([]byte, error) {
|
||||
return json.MarshalIndent(jsonPayload{
|
||||
ChainID: chainID.Uint64(),
|
||||
Block: block,
|
||||
Witness: ext,
|
||||
}, "", " ")
|
||||
}
|
||||
|
||||
func fatal(format string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
@ -1,408 +0,0 @@
|
|||
// Copyright 2026 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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ethereum/go-ethereum/trie/bintrie"
|
||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
deleteSourceFlag = &cli.BoolFlag{
|
||||
Name: "delete-source",
|
||||
Usage: "Delete MPT trie nodes after conversion",
|
||||
}
|
||||
memoryLimitFlag = &cli.Uint64Flag{
|
||||
Name: "memory-limit",
|
||||
Usage: "Max heap allocation in MB before forcing a commit cycle",
|
||||
Value: 16384,
|
||||
}
|
||||
|
||||
bintrieCommand = &cli.Command{
|
||||
Name: "bintrie",
|
||||
Usage: "A set of commands for binary trie operations",
|
||||
Description: "",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "convert",
|
||||
Usage: "Convert MPT state to binary trie",
|
||||
ArgsUsage: "[state-root]",
|
||||
Action: convertToBinaryTrie,
|
||||
Flags: slices.Concat([]cli.Flag{
|
||||
deleteSourceFlag,
|
||||
memoryLimitFlag,
|
||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||
Description: `
|
||||
geth bintrie convert [--delete-source] [--memory-limit MB] [state-root]
|
||||
|
||||
Reads all state from the Merkle Patricia Trie and writes it into a Binary Trie,
|
||||
operating offline. Memory-safe via periodic commit-and-reload cycles.
|
||||
|
||||
The optional state-root argument specifies which state root to convert.
|
||||
If omitted, the head block's state root is used.
|
||||
|
||||
Flags:
|
||||
--delete-source Delete MPT trie nodes after successful conversion
|
||||
--memory-limit Max heap allocation in MB before forcing a commit (default: 16384)
|
||||
`,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type conversionStats struct {
|
||||
accounts uint64
|
||||
slots uint64
|
||||
codes uint64
|
||||
commits uint64
|
||||
start time.Time
|
||||
lastReport time.Time
|
||||
lastMemChk time.Time
|
||||
}
|
||||
|
||||
func (s *conversionStats) report(force bool) {
|
||||
if !force && time.Since(s.lastReport) < 8*time.Second {
|
||||
return
|
||||
}
|
||||
elapsed := time.Since(s.start).Seconds()
|
||||
acctRate := float64(0)
|
||||
if elapsed > 0 {
|
||||
acctRate = float64(s.accounts) / elapsed
|
||||
}
|
||||
log.Info("Conversion progress",
|
||||
"accounts", s.accounts,
|
||||
"slots", s.slots,
|
||||
"codes", s.codes,
|
||||
"commits", s.commits,
|
||||
"accounts/sec", fmt.Sprintf("%.0f", acctRate),
|
||||
"elapsed", common.PrettyDuration(time.Since(s.start)),
|
||||
)
|
||||
s.lastReport = time.Now()
|
||||
}
|
||||
|
||||
func convertToBinaryTrie(ctx *cli.Context) error {
|
||||
if ctx.NArg() > 1 {
|
||||
return errors.New("too many arguments")
|
||||
}
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
chaindb := utils.MakeChainDatabase(ctx, stack, false)
|
||||
defer chaindb.Close()
|
||||
|
||||
headBlock := rawdb.ReadHeadBlock(chaindb)
|
||||
if headBlock == nil {
|
||||
return errors.New("no head block found")
|
||||
}
|
||||
var (
|
||||
root common.Hash
|
||||
err error
|
||||
)
|
||||
if ctx.NArg() == 1 {
|
||||
root, err = parseRoot(ctx.Args().First())
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid state root: %w", err)
|
||||
}
|
||||
} else {
|
||||
root = headBlock.Root()
|
||||
}
|
||||
log.Info("Starting MPT to binary trie conversion", "root", root, "block", headBlock.NumberU64())
|
||||
|
||||
srcTriedb := utils.MakeTrieDatabase(ctx, stack, chaindb, true, true, false)
|
||||
defer srcTriedb.Close()
|
||||
|
||||
destTriedb := triedb.NewDatabase(chaindb, &triedb.Config{
|
||||
IsUBT: true,
|
||||
PathDB: &pathdb.Config{
|
||||
JournalDirectory: stack.ResolvePath("triedb-bintrie"),
|
||||
},
|
||||
})
|
||||
defer destTriedb.Close()
|
||||
|
||||
binTrie, err := bintrie.NewBinaryTrie(types.EmptyBinaryHash, destTriedb, ctx.Int(utils.BinTrieGroupDepthFlag.Name))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create binary trie: %w", err)
|
||||
}
|
||||
memLimit := ctx.Uint64(memoryLimitFlag.Name) * 1024 * 1024
|
||||
|
||||
currentRoot, err := runConversionLoop(chaindb, srcTriedb, destTriedb, binTrie, root, memLimit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info("Conversion complete", "binaryRoot", currentRoot)
|
||||
|
||||
if ctx.Bool(deleteSourceFlag.Name) {
|
||||
log.Info("Deleting source MPT data")
|
||||
if err := deleteMPTData(chaindb, srcTriedb, root); err != nil {
|
||||
return fmt.Errorf("MPT deletion failed: %w", err)
|
||||
}
|
||||
log.Info("Source MPT data deleted")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runConversionLoop(chaindb ethdb.Database, srcTriedb *triedb.Database, destTriedb *triedb.Database, binTrie *bintrie.BinaryTrie, root common.Hash, memLimit uint64) (common.Hash, error) {
|
||||
currentRoot := types.EmptyBinaryHash
|
||||
stats := &conversionStats{
|
||||
start: time.Now(),
|
||||
lastReport: time.Now(),
|
||||
lastMemChk: time.Now(),
|
||||
}
|
||||
|
||||
srcTrie, err := trie.NewStateTrie(trie.StateTrieID(root), srcTriedb)
|
||||
if err != nil {
|
||||
return common.Hash{}, fmt.Errorf("failed to open source trie: %w", err)
|
||||
}
|
||||
acctIt, err := srcTrie.NodeIterator(nil)
|
||||
if err != nil {
|
||||
return common.Hash{}, fmt.Errorf("failed to create account iterator: %w", err)
|
||||
}
|
||||
accIter := trie.NewIterator(acctIt)
|
||||
|
||||
for accIter.Next() {
|
||||
var acc types.StateAccount
|
||||
if err := rlp.DecodeBytes(accIter.Value, &acc); err != nil {
|
||||
return common.Hash{}, fmt.Errorf("invalid account RLP: %w", err)
|
||||
}
|
||||
addrBytes := srcTrie.GetKey(accIter.Key)
|
||||
if addrBytes == nil {
|
||||
return common.Hash{}, fmt.Errorf("missing preimage for account hash %x (run with --cache.preimages)", accIter.Key)
|
||||
}
|
||||
addr := common.BytesToAddress(addrBytes)
|
||||
|
||||
var code []byte
|
||||
codeHash := common.BytesToHash(acc.CodeHash)
|
||||
if codeHash != types.EmptyCodeHash {
|
||||
code = rawdb.ReadCode(chaindb, codeHash)
|
||||
if code == nil {
|
||||
return common.Hash{}, fmt.Errorf("missing code for hash %x (account %x)", codeHash, addr)
|
||||
}
|
||||
stats.codes++
|
||||
}
|
||||
|
||||
if err := binTrie.UpdateAccount(addr, &acc, len(code)); err != nil {
|
||||
return common.Hash{}, fmt.Errorf("failed to update account %x: %w", addr, err)
|
||||
}
|
||||
if len(code) > 0 {
|
||||
if err := binTrie.UpdateContractCode(addr, codeHash, code); err != nil {
|
||||
return common.Hash{}, fmt.Errorf("failed to update code for %x: %w", addr, err)
|
||||
}
|
||||
}
|
||||
|
||||
if acc.Root != types.EmptyRootHash {
|
||||
addrHash := common.BytesToHash(accIter.Key)
|
||||
storageTrie, err := trie.NewStateTrie(trie.StorageTrieID(root, addrHash, acc.Root), srcTriedb)
|
||||
if err != nil {
|
||||
return common.Hash{}, fmt.Errorf("failed to open storage trie for %x: %w", addr, err)
|
||||
}
|
||||
storageNodeIt, err := storageTrie.NodeIterator(nil)
|
||||
if err != nil {
|
||||
return common.Hash{}, fmt.Errorf("failed to create storage iterator for %x: %w", addr, err)
|
||||
}
|
||||
storageIter := trie.NewIterator(storageNodeIt)
|
||||
|
||||
slotCount := uint64(0)
|
||||
for storageIter.Next() {
|
||||
slotKey := storageTrie.GetKey(storageIter.Key)
|
||||
if slotKey == nil {
|
||||
return common.Hash{}, fmt.Errorf("missing preimage for storage key %x (account %x)", storageIter.Key, addr)
|
||||
}
|
||||
_, content, _, err := rlp.Split(storageIter.Value)
|
||||
if err != nil {
|
||||
return common.Hash{}, fmt.Errorf("invalid storage RLP for key %x (account %x): %w", slotKey, addr, err)
|
||||
}
|
||||
if err := binTrie.UpdateStorage(addr, slotKey, content); err != nil {
|
||||
return common.Hash{}, fmt.Errorf("failed to update storage %x/%x: %w", addr, slotKey, err)
|
||||
}
|
||||
stats.slots++
|
||||
slotCount++
|
||||
|
||||
if slotCount%10000 == 0 {
|
||||
binTrie, currentRoot, err = maybeCommit(binTrie, currentRoot, destTriedb, memLimit, stats)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if storageIter.Err != nil {
|
||||
return common.Hash{}, fmt.Errorf("storage iteration error for %x: %w", addr, storageIter.Err)
|
||||
}
|
||||
}
|
||||
stats.accounts++
|
||||
stats.report(false)
|
||||
|
||||
if stats.accounts%1000 == 0 {
|
||||
binTrie, currentRoot, err = maybeCommit(binTrie, currentRoot, destTriedb, memLimit, stats)
|
||||
if err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if accIter.Err != nil {
|
||||
return common.Hash{}, fmt.Errorf("account iteration error: %w", accIter.Err)
|
||||
}
|
||||
|
||||
_, currentRoot, err = commitBinaryTrie(binTrie, currentRoot, destTriedb)
|
||||
if err != nil {
|
||||
return common.Hash{}, fmt.Errorf("final commit failed: %w", err)
|
||||
}
|
||||
stats.commits++
|
||||
stats.report(true)
|
||||
return currentRoot, nil
|
||||
}
|
||||
|
||||
func maybeCommit(bt *bintrie.BinaryTrie, currentRoot common.Hash, destDB *triedb.Database, memLimit uint64, stats *conversionStats) (*bintrie.BinaryTrie, common.Hash, error) {
|
||||
if time.Since(stats.lastMemChk) < 5*time.Second {
|
||||
return bt, currentRoot, nil
|
||||
}
|
||||
stats.lastMemChk = time.Now()
|
||||
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
if m.Alloc < memLimit {
|
||||
return bt, currentRoot, nil
|
||||
}
|
||||
log.Info("Memory limit reached, committing", "alloc", common.StorageSize(m.Alloc), "limit", common.StorageSize(memLimit))
|
||||
|
||||
bt, currentRoot, err := commitBinaryTrie(bt, currentRoot, destDB)
|
||||
if err != nil {
|
||||
return nil, common.Hash{}, err
|
||||
}
|
||||
stats.commits++
|
||||
stats.report(true)
|
||||
return bt, currentRoot, nil
|
||||
}
|
||||
|
||||
func commitBinaryTrie(bt *bintrie.BinaryTrie, currentRoot common.Hash, destDB *triedb.Database) (*bintrie.BinaryTrie, common.Hash, error) {
|
||||
newRoot, nodeSet := bt.Commit(false)
|
||||
if nodeSet != nil {
|
||||
merged := trienode.NewWithNodeSet(nodeSet)
|
||||
if err := destDB.Update(newRoot, currentRoot, 0, merged, triedb.NewStateSet()); err != nil {
|
||||
return nil, common.Hash{}, fmt.Errorf("triedb update failed: %w", err)
|
||||
}
|
||||
if err := destDB.Commit(newRoot, false); err != nil {
|
||||
return nil, common.Hash{}, fmt.Errorf("triedb commit failed: %w", err)
|
||||
}
|
||||
}
|
||||
runtime.GC()
|
||||
debug.FreeOSMemory()
|
||||
|
||||
bt, err := bintrie.NewBinaryTrie(newRoot, destDB, bt.GroupDepth())
|
||||
if err != nil {
|
||||
return nil, common.Hash{}, fmt.Errorf("failed to reload binary trie: %w", err)
|
||||
}
|
||||
return bt, newRoot, nil
|
||||
}
|
||||
|
||||
func deleteMPTData(chaindb ethdb.Database, srcTriedb *triedb.Database, root common.Hash) error {
|
||||
isPathDB := srcTriedb.Scheme() == rawdb.PathScheme
|
||||
|
||||
srcTrie, err := trie.NewStateTrie(trie.StateTrieID(root), srcTriedb)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open source trie for deletion: %w", err)
|
||||
}
|
||||
acctIt, err := srcTrie.NodeIterator(nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create account iterator for deletion: %w", err)
|
||||
}
|
||||
batch := chaindb.NewBatch()
|
||||
deleted := 0
|
||||
|
||||
for acctIt.Next(true) {
|
||||
if isPathDB {
|
||||
rawdb.DeleteAccountTrieNode(batch, acctIt.Path())
|
||||
} else {
|
||||
node := acctIt.Hash()
|
||||
if node != (common.Hash{}) {
|
||||
rawdb.DeleteLegacyTrieNode(batch, node)
|
||||
}
|
||||
}
|
||||
deleted++
|
||||
|
||||
if acctIt.Leaf() {
|
||||
var acc types.StateAccount
|
||||
if err := rlp.DecodeBytes(acctIt.LeafBlob(), &acc); err != nil {
|
||||
return fmt.Errorf("invalid account during deletion: %w", err)
|
||||
}
|
||||
if acc.Root != types.EmptyRootHash {
|
||||
addrHash := common.BytesToHash(acctIt.LeafKey())
|
||||
storageTrie, err := trie.NewStateTrie(trie.StorageTrieID(root, addrHash, acc.Root), srcTriedb)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open storage trie for deletion: %w", err)
|
||||
}
|
||||
storageIt, err := storageTrie.NodeIterator(nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create storage iterator for deletion: %w", err)
|
||||
}
|
||||
for storageIt.Next(true) {
|
||||
if isPathDB {
|
||||
rawdb.DeleteStorageTrieNode(batch, addrHash, storageIt.Path())
|
||||
} else {
|
||||
node := storageIt.Hash()
|
||||
if node != (common.Hash{}) {
|
||||
rawdb.DeleteLegacyTrieNode(batch, node)
|
||||
}
|
||||
}
|
||||
deleted++
|
||||
if batch.ValueSize() >= ethdb.IdealBatchSize {
|
||||
if err := batch.Write(); err != nil {
|
||||
return fmt.Errorf("batch write failed: %w", err)
|
||||
}
|
||||
batch.Reset()
|
||||
}
|
||||
}
|
||||
if storageIt.Error() != nil {
|
||||
return fmt.Errorf("storage deletion iterator error: %w", storageIt.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
if batch.ValueSize() >= ethdb.IdealBatchSize {
|
||||
if err := batch.Write(); err != nil {
|
||||
return fmt.Errorf("batch write failed: %w", err)
|
||||
}
|
||||
batch.Reset()
|
||||
}
|
||||
}
|
||||
if acctIt.Error() != nil {
|
||||
return fmt.Errorf("account deletion iterator error: %w", acctIt.Error())
|
||||
}
|
||||
if batch.ValueSize() > 0 {
|
||||
if err := batch.Write(); err != nil {
|
||||
return fmt.Errorf("final batch write failed: %w", err)
|
||||
}
|
||||
}
|
||||
log.Info("MPT deletion complete", "nodesDeleted", deleted)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,229 +0,0 @@
|
|||
// Copyright 2026 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 (
|
||||
"math"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/trie/bintrie"
|
||||
"github.com/ethereum/go-ethereum/triedb"
|
||||
"github.com/ethereum/go-ethereum/triedb/pathdb"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
func TestBintrieConvert(t *testing.T) {
|
||||
var (
|
||||
addr1 = common.HexToAddress("0x1111111111111111111111111111111111111111")
|
||||
addr2 = common.HexToAddress("0x2222222222222222222222222222222222222222")
|
||||
slotKey1 = common.HexToHash("0x01")
|
||||
slotKey2 = common.HexToHash("0x02")
|
||||
slotVal1 = common.HexToHash("0xdeadbeef")
|
||||
slotVal2 = common.HexToHash("0xcafebabe")
|
||||
code = []byte{0x60, 0x42, 0x60, 0x00, 0x52, 0x60, 0x20, 0x60, 0x00, 0xf3}
|
||||
)
|
||||
|
||||
chaindb := rawdb.NewMemoryDatabase()
|
||||
|
||||
srcTriedb := triedb.NewDatabase(chaindb, &triedb.Config{
|
||||
Preimages: true,
|
||||
PathDB: pathdb.Defaults,
|
||||
})
|
||||
|
||||
gspec := &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||
Alloc: types.GenesisAlloc{
|
||||
addr1: {
|
||||
Balance: big.NewInt(1000000),
|
||||
Nonce: 5,
|
||||
},
|
||||
addr2: {
|
||||
Balance: big.NewInt(2000000),
|
||||
Nonce: 10,
|
||||
Code: code,
|
||||
Storage: map[common.Hash]common.Hash{
|
||||
slotKey1: slotVal1,
|
||||
slotKey2: slotVal2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
genesisBlock := gspec.MustCommit(chaindb, srcTriedb)
|
||||
root := genesisBlock.Root()
|
||||
t.Logf("Genesis root: %x", root)
|
||||
srcTriedb.Close()
|
||||
|
||||
srcTriedb2 := triedb.NewDatabase(chaindb, &triedb.Config{
|
||||
Preimages: true,
|
||||
PathDB: &pathdb.Config{ReadOnly: true},
|
||||
})
|
||||
defer srcTriedb2.Close()
|
||||
|
||||
destTriedb := triedb.NewDatabase(chaindb, &triedb.Config{
|
||||
IsUBT: true,
|
||||
PathDB: pathdb.Defaults,
|
||||
})
|
||||
defer destTriedb.Close()
|
||||
|
||||
bt, err := bintrie.NewBinaryTrie(types.EmptyBinaryHash, destTriedb, 8)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create binary trie: %v", err)
|
||||
}
|
||||
|
||||
currentRoot, err := runConversionLoop(chaindb, srcTriedb2, destTriedb, bt, root, math.MaxUint64)
|
||||
if err != nil {
|
||||
t.Fatalf("conversion failed: %v", err)
|
||||
}
|
||||
t.Logf("Binary trie root: %x", currentRoot)
|
||||
|
||||
bt2, err := bintrie.NewBinaryTrie(currentRoot, destTriedb, 8)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to reload binary trie: %v", err)
|
||||
}
|
||||
|
||||
acc1, err := bt2.GetAccount(addr1)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get account1: %v", err)
|
||||
}
|
||||
if acc1 == nil {
|
||||
t.Fatal("account1 not found in binary trie")
|
||||
}
|
||||
if acc1.Nonce != 5 {
|
||||
t.Errorf("account1 nonce: got %d, want 5", acc1.Nonce)
|
||||
}
|
||||
wantBal1 := uint256.NewInt(1000000)
|
||||
if acc1.Balance.Cmp(wantBal1) != 0 {
|
||||
t.Errorf("account1 balance: got %s, want %s", acc1.Balance, wantBal1)
|
||||
}
|
||||
|
||||
acc2, err := bt2.GetAccount(addr2)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get account2: %v", err)
|
||||
}
|
||||
if acc2 == nil {
|
||||
t.Fatal("account2 not found in binary trie")
|
||||
}
|
||||
if acc2.Nonce != 10 {
|
||||
t.Errorf("account2 nonce: got %d, want 10", acc2.Nonce)
|
||||
}
|
||||
wantBal2 := uint256.NewInt(2000000)
|
||||
if acc2.Balance.Cmp(wantBal2) != 0 {
|
||||
t.Errorf("account2 balance: got %s, want %s", acc2.Balance, wantBal2)
|
||||
}
|
||||
|
||||
treeKey1 := bintrie.GetBinaryTreeKeyStorageSlot(addr2, slotKey1[:])
|
||||
val1, err := bt2.GetWithHashedKey(treeKey1)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get storage slot1: %v", err)
|
||||
}
|
||||
if len(val1) == 0 {
|
||||
t.Fatal("storage slot1 not found")
|
||||
}
|
||||
got1 := common.BytesToHash(val1)
|
||||
if got1 != slotVal1 {
|
||||
t.Errorf("storage slot1: got %x, want %x", got1, slotVal1)
|
||||
}
|
||||
|
||||
treeKey2 := bintrie.GetBinaryTreeKeyStorageSlot(addr2, slotKey2[:])
|
||||
val2, err := bt2.GetWithHashedKey(treeKey2)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get storage slot2: %v", err)
|
||||
}
|
||||
if len(val2) == 0 {
|
||||
t.Fatal("storage slot2 not found")
|
||||
}
|
||||
got2 := common.BytesToHash(val2)
|
||||
if got2 != slotVal2 {
|
||||
t.Errorf("storage slot2: got %x, want %x", got2, slotVal2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBintrieConvertDeleteSource(t *testing.T) {
|
||||
addr1 := common.HexToAddress("0x3333333333333333333333333333333333333333")
|
||||
|
||||
chaindb := rawdb.NewMemoryDatabase()
|
||||
|
||||
srcTriedb := triedb.NewDatabase(chaindb, &triedb.Config{
|
||||
Preimages: true,
|
||||
PathDB: pathdb.Defaults,
|
||||
})
|
||||
|
||||
gspec := &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||
Alloc: types.GenesisAlloc{
|
||||
addr1: {
|
||||
Balance: big.NewInt(1000000),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
genesisBlock := gspec.MustCommit(chaindb, srcTriedb)
|
||||
root := genesisBlock.Root()
|
||||
srcTriedb.Close()
|
||||
|
||||
srcTriedb2 := triedb.NewDatabase(chaindb, &triedb.Config{
|
||||
Preimages: true,
|
||||
PathDB: &pathdb.Config{ReadOnly: true},
|
||||
})
|
||||
|
||||
destTriedb := triedb.NewDatabase(chaindb, &triedb.Config{
|
||||
IsUBT: true,
|
||||
PathDB: pathdb.Defaults,
|
||||
})
|
||||
|
||||
bt, err := bintrie.NewBinaryTrie(types.EmptyBinaryHash, destTriedb, 8)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create binary trie: %v", err)
|
||||
}
|
||||
|
||||
newRoot, err := runConversionLoop(chaindb, srcTriedb2, destTriedb, bt, root, math.MaxUint64)
|
||||
if err != nil {
|
||||
t.Fatalf("conversion failed: %v", err)
|
||||
}
|
||||
|
||||
if err := deleteMPTData(chaindb, srcTriedb2, root); err != nil {
|
||||
t.Fatalf("deletion failed: %v", err)
|
||||
}
|
||||
srcTriedb2.Close()
|
||||
|
||||
bt2, err := bintrie.NewBinaryTrie(newRoot, destTriedb, 8)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to reload binary trie after deletion: %v", err)
|
||||
}
|
||||
|
||||
acc, err := bt2.GetAccount(addr1)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get account after deletion: %v", err)
|
||||
}
|
||||
if acc == nil {
|
||||
t.Fatal("account not found after MPT deletion")
|
||||
}
|
||||
wantBal := uint256.NewInt(1000000)
|
||||
if acc.Balance.Cmp(wantBal) != 0 {
|
||||
t.Errorf("balance after deletion: got %s, want %s", acc.Balance, wantBal)
|
||||
}
|
||||
destTriedb.Close()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue