Merge branch 'master' into tracing/v1.1

This commit is contained in:
Sina Mahmoodi 2024-12-03 16:20:51 +01:00
commit 1dda30d353
32 changed files with 631 additions and 582 deletions

39
.github/CODEOWNERS vendored
View File

@ -1,25 +1,36 @@
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners.
accounts/usbwallet @karalabe
accounts/scwallet @gballet
accounts/abi @gballet @MariusVanDerWijden
beacon/engine @lightclient
cmd/clef @holiman
cmd/evm @holiman @MariusVanDerWijden @lightclient
consensus @karalabe
core/ @karalabe @holiman @rjl493456442
eth/ @karalabe @holiman @rjl493456442
eth/catalyst/ @gballet @lightclient
accounts/usbwallet/ @gballet
accounts/scwallet/ @gballet
accounts/abi/ @gballet @MariusVanDerWijden
beacon/engine/ @MariusVanDerWijden @lightclient @fjl
beacon/light/ @zsfelfoldi
beacon/merkle/ @zsfelfoldi
beacon/types/ @zsfelfoldi @fjl
beacon/params/ @zsfelfoldi @fjl
cmd/clef/ @holiman
cmd/evm/ @holiman @MariusVanDerWijden @lightclient
core/state/ @rjl493456442 @holiman
crypto/ @gballet @jwasinger @holiman @fjl
core/ @holiman @rjl493456442
eth/ @holiman @rjl493456442
eth/catalyst/ @MariusVanDerWijden @lightclient @fjl @jwasinger
eth/tracers/ @s1na
ethclient/ @fjl
ethdb/ @rjl493456442
event/ @fjl
trie/ @rjl493456442
triedb/ @rjl493456442
core/tracing/ @s1na
graphql/ @s1na
internal/ethapi @lightclient
internal/era @lightclient
les/ @zsfelfoldi @rjl493456442
light/ @zsfelfoldi @rjl493456442
internal/ethapi/ @fjl @s1na @lightclient
internal/era/ @lightclient
metrics/ @holiman
miner/ @MariusVanDerWijden @holiman @fjl @rjl493456442
node/ @fjl
p2p/ @fjl @zsfelfoldi
rlp/ @fjl
params/ @fjl @holiman @karalabe @gballet @rjl493456442 @zsfelfoldi
rpc/ @fjl @holiman
signer/ @holiman

View File

@ -22,79 +22,84 @@ import (
"fmt"
"os"
"regexp"
"sort"
"slices"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/tests"
"github.com/urfave/cli/v2"
"golang.org/x/exp/maps"
)
var RunFlag = &cli.StringFlag{
Name: "run",
Value: ".*",
Usage: "Run only those tests matching the regular expression.",
}
var blockTestCommand = &cli.Command{
Action: blockTestCmd,
Name: "blocktest",
Usage: "Executes the given blockchain tests",
ArgsUsage: "<file>",
Flags: []cli.Flag{RunFlag},
ArgsUsage: "<path>",
Flags: slices.Concat([]cli.Flag{
DumpFlag,
HumanReadableFlag,
RunFlag,
WitnessCrossCheckFlag,
}, traceFlags),
}
func blockTestCmd(ctx *cli.Context) error {
if len(ctx.Args().First()) == 0 {
return errors.New("path-to-test argument required")
path := ctx.Args().First()
if len(path) == 0 {
return errors.New("path argument required")
}
var (
collected = collectJSONFiles(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
}
var tracer *tracing.Hooks
// Configure the EVM logger
if ctx.Bool(MachineFlag.Name) {
tracer = logger.NewJSONLogger(&logger.Config{
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
DisableStack: ctx.Bool(DisableStackFlag.Name),
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
}, os.Stderr)
}
// Load the test content from the input file
src, err := os.ReadFile(ctx.Args().First())
func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
src, err := os.ReadFile(fname)
if err != nil {
return err
return nil, err
}
var tests map[string]tests.BlockTest
var tests map[string]*tests.BlockTest
if err = json.Unmarshal(src, &tests); err != nil {
return err
return nil, err
}
re, err := regexp.Compile(ctx.String(RunFlag.Name))
if err != nil {
return fmt.Errorf("invalid regex -%s: %v", RunFlag.Name, err)
return nil, fmt.Errorf("invalid regex -%s: %v", RunFlag.Name, err)
}
tracer := tracerFromFlags(ctx)
// Run them in order
var keys []string
for key := range tests {
keys = append(keys, key)
}
sort.Strings(keys)
// Pull out keys to sort and ensure tests are run in order.
keys := maps.Keys(tests)
slices.Sort(keys)
// Run all the tests.
var results []testResult
for _, name := range keys {
if !re.MatchString(name) {
continue
}
test := tests[name]
if err := test.Run(false, rawdb.HashScheme, false, tracer, func(res error, chain *core.BlockChain) {
result := &testResult{Name: name, Pass: true}
if err := tests[name].Run(false, rawdb.HashScheme, ctx.Bool(WitnessCrossCheckFlag.Name), tracer, func(res error, chain *core.BlockChain) {
if ctx.Bool(DumpFlag.Name) {
if state, _ := chain.State(); state != nil {
fmt.Println(string(state.Dump(nil)))
if s, _ := chain.State(); s != nil {
result.State = dump(s)
}
}
}); err != nil {
return fmt.Errorf("test %v: %w", name, err)
result.Pass, result.Error = false, err.Error()
}
results = append(results, *result)
}
return nil
return results, nil
}

View File

@ -1,55 +0,0 @@
// Copyright 2017 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"
"os"
"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler"
"github.com/urfave/cli/v2"
)
var compileCommand = &cli.Command{
Action: compileCmd,
Name: "compile",
Usage: "Compiles easm source to evm binary",
ArgsUsage: "<file>",
}
func compileCmd(ctx *cli.Context) error {
debug := ctx.Bool(DebugFlag.Name)
if len(ctx.Args().First()) == 0 {
return errors.New("filename required")
}
fn := ctx.Args().First()
src, err := os.ReadFile(fn)
if err != nil {
return err
}
bin, err := compiler.Compile(fn, src, debug)
if err != nil {
return err
}
fmt.Println(bin)
return nil
}

View File

@ -1,55 +0,0 @@
// Copyright 2017 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"
"os"
"strings"
"github.com/ethereum/go-ethereum/core/asm"
"github.com/urfave/cli/v2"
)
var disasmCommand = &cli.Command{
Action: disasmCmd,
Name: "disasm",
Usage: "Disassembles evm binary",
ArgsUsage: "<file>",
}
func disasmCmd(ctx *cli.Context) error {
var in string
switch {
case len(ctx.Args().First()) > 0:
fn := ctx.Args().First()
input, err := os.ReadFile(fn)
if err != nil {
return err
}
in = string(input)
case ctx.IsSet(InputFlag.Name):
in = ctx.String(InputFlag.Name)
default:
return errors.New("missing filename or --input value")
}
code := strings.TrimSpace(in)
fmt.Printf("%v\n", code)
return asm.PrintDisassembled(code)
}

49
cmd/evm/eest.go Normal file
View File

@ -0,0 +1,49 @@
// Copyright 2024 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 "regexp"
// testMetadata provides more granular access to the test information encoded
// within its filename by the execution spec test (EEST).
type testMetadata struct {
fork string
module string // which python module gnerated the test, e.g. eip7702
file string // exact file the test came from, e.g. test_gas.py
function string // func that created the test, e.g. test_valid_mcopy_operations
parameters string // the name of the parameters which were used to fill the test, e.g. zero_inputs
}
// parseTestMetadata reads a test name and parses out more specific information
// about the test.
func parseTestMetadata(s string) *testMetadata {
var (
pattern = `tests\/([^\/]+)\/([^\/]+)\/([^:]+)::([^[]+)\[fork_([^-\]]+)-[^-]+-(.+)\]`
re = regexp.MustCompile(pattern)
)
match := re.FindStringSubmatch(s)
if len(match) == 0 {
return nil
}
return &testMetadata{
fork: match[5],
module: match[2],
file: match[3],
function: match[4],
parameters: match[6],
}
}

View File

@ -31,13 +31,41 @@ import (
"github.com/urfave/cli/v2"
)
var jt vm.JumpTable
const initcode = "INITCODE"
func init() {
jt = vm.NewPragueEOFInstructionSetForTesting()
}
var (
jt vm.JumpTable
initcode = "INITCODE"
hexFlag = &cli.StringFlag{
Name: "hex",
Usage: "Single container data parse and validation",
}
refTestFlag = &cli.StringFlag{
Name: "test",
Usage: "Path to EOF validation reference test.",
}
eofParseCommand = &cli.Command{
Name: "eofparse",
Aliases: []string{"eof"},
Usage: "Parses hex eof container and returns validation errors (if any)",
Action: eofParseAction,
Flags: []cli.Flag{
hexFlag,
refTestFlag,
},
}
eofDumpCommand = &cli.Command{
Name: "eofdump",
Usage: "Parses hex eof container and prints out human-readable representation of the container.",
Action: eofDumpAction,
Flags: []cli.Flag{
hexFlag,
},
}
)
func eofParseAction(ctx *cli.Context) error {

View File

@ -1,39 +0,0 @@
// Copyright 2017 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 compiler
import (
"errors"
"fmt"
"github.com/ethereum/go-ethereum/core/asm"
)
func Compile(fn string, src []byte, debug bool) (string, error) {
compiler := asm.NewCompiler(debug)
compiler.Feed(asm.Lex(src, debug))
bin, compileErrors := compiler.Compile()
if len(compileErrors) > 0 {
// report errors
for _, err := range compileErrors {
fmt.Printf("%s:%v\n", fn, err)
}
return "", errors.New("compiling failed")
}
return bin, nil
}

View File

@ -19,11 +19,14 @@ package main
import (
"fmt"
"math/big"
"io/fs"
"os"
"slices"
"path/filepath"
"github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/urfave/cli/v2"
@ -33,122 +36,100 @@ import (
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
)
// Some other nice-to-haves:
// * accumulate traces into an object to bundle with test
// * write tx identifier for trace before hand (blocktest only)
// * combine blocktest and statetest runner logic using unified test interface
const traceCategory = "TRACING"
var (
DebugFlag = &cli.BoolFlag{
Name: "debug",
Usage: "output full trace logs",
Category: flags.VMCategory,
}
StatDumpFlag = &cli.BoolFlag{
Name: "statdump",
Usage: "displays stack and heap memory information",
Category: flags.VMCategory,
}
CodeFlag = &cli.StringFlag{
Name: "code",
Usage: "EVM code",
Category: flags.VMCategory,
}
CodeFileFlag = &cli.StringFlag{
Name: "codefile",
Usage: "File containing EVM code. If '-' is specified, code is read from stdin ",
Category: flags.VMCategory,
}
GasFlag = &cli.Uint64Flag{
Name: "gas",
Usage: "gas limit for the evm",
Value: 10000000000,
Category: flags.VMCategory,
}
PriceFlag = &flags.BigFlag{
Name: "price",
Usage: "price set for the evm",
Value: new(big.Int),
Category: flags.VMCategory,
}
ValueFlag = &flags.BigFlag{
Name: "value",
Usage: "value set for the evm",
Value: new(big.Int),
Category: flags.VMCategory,
}
DumpFlag = &cli.BoolFlag{
Name: "dump",
Usage: "dumps the state after the run",
Category: flags.VMCategory,
}
InputFlag = &cli.StringFlag{
Name: "input",
Usage: "input for the EVM",
Category: flags.VMCategory,
}
InputFileFlag = &cli.StringFlag{
Name: "inputfile",
Usage: "file containing input for the EVM",
Category: flags.VMCategory,
// Test running flags.
RunFlag = &cli.StringFlag{
Name: "run",
Value: ".*",
Usage: "Run only those tests matching the regular expression.",
}
BenchFlag = &cli.BoolFlag{
Name: "bench",
Usage: "benchmark the execution",
Category: flags.VMCategory,
}
CreateFlag = &cli.BoolFlag{
Name: "create",
Usage: "indicates the action should be create rather than call",
Category: flags.VMCategory,
WitnessCrossCheckFlag = &cli.BoolFlag{
Name: "cross-check",
Aliases: []string{"xc"},
Usage: "Cross-check stateful execution against stateless, verifying the witness generation.",
}
GenesisFlag = &cli.StringFlag{
Name: "prestate",
Usage: "JSON file with prestate (genesis) config",
Category: flags.VMCategory,
// Debugging flags.
DumpFlag = &cli.BoolFlag{
Name: "dump",
Usage: "dumps the state after the run",
}
HumanReadableFlag = &cli.BoolFlag{
Name: "human",
Usage: "\"Human-readable\" output",
}
StatDumpFlag = &cli.BoolFlag{
Name: "statdump",
Usage: "displays stack and heap memory information",
}
// Tracing flags.
TraceFlag = &cli.BoolFlag{
Name: "trace",
Usage: "Enable tracing and output trace log.",
Category: traceCategory,
}
TraceFormatFlag = &cli.StringFlag{
Name: "trace.format",
Usage: "Trace output format to use (struct|json)",
Value: "struct",
Category: traceCategory,
}
TraceDisableMemoryFlag = &cli.BoolFlag{
Name: "trace.nomemory",
Aliases: []string{"nomemory"},
Value: true,
Usage: "disable memory output",
Category: traceCategory,
}
TraceDisableStackFlag = &cli.BoolFlag{
Name: "trace.nostack",
Aliases: []string{"nostack"},
Usage: "disable stack output",
Category: traceCategory,
}
TraceDisableStorageFlag = &cli.BoolFlag{
Name: "trace.nostorage",
Aliases: []string{"nostorage"},
Usage: "disable storage output",
Category: traceCategory,
}
TraceDisableReturnDataFlag = &cli.BoolFlag{
Name: "trace.noreturndata",
Aliases: []string{"noreturndata"},
Value: true,
Usage: "enable return data output",
Category: traceCategory,
}
// Deprecated flags.
DebugFlag = &cli.BoolFlag{
Name: "debug",
Usage: "output full trace logs (deprecated)",
Hidden: true,
Category: traceCategory,
}
MachineFlag = &cli.BoolFlag{
Name: "json",
Usage: "output trace logs in machine readable format (json)",
Category: flags.VMCategory,
}
SenderFlag = &cli.StringFlag{
Name: "sender",
Usage: "The transaction origin",
Category: flags.VMCategory,
}
ReceiverFlag = &cli.StringFlag{
Name: "receiver",
Usage: "The transaction receiver (execution context)",
Category: flags.VMCategory,
}
DisableMemoryFlag = &cli.BoolFlag{
Name: "nomemory",
Value: true,
Usage: "disable memory output",
Category: flags.VMCategory,
}
DisableStackFlag = &cli.BoolFlag{
Name: "nostack",
Usage: "disable stack output",
Category: flags.VMCategory,
}
DisableStorageFlag = &cli.BoolFlag{
Name: "nostorage",
Usage: "disable storage output",
Category: flags.VMCategory,
}
DisableReturnDataFlag = &cli.BoolFlag{
Name: "noreturndata",
Value: true,
Usage: "enable return data output",
Category: flags.VMCategory,
}
refTestFlag = &cli.StringFlag{
Name: "test",
Usage: "Path to EOF validation reference test.",
}
hexFlag = &cli.StringFlag{
Name: "hex",
Usage: "single container data parse and validation",
Usage: "output trace logs in machine readable format, json (deprecated)",
Hidden: true,
Category: traceCategory,
}
)
// Command definitions.
var (
stateTransitionCommand = &cli.Command{
Name: "transition",
@ -175,7 +156,6 @@ var (
t8ntool.RewardFlag,
},
}
transactionCommand = &cli.Command{
Name: "transaction",
Aliases: []string{"t9n"},
@ -203,62 +183,27 @@ var (
t8ntool.SealCliqueFlag,
},
}
eofParseCommand = &cli.Command{
Name: "eofparse",
Aliases: []string{"eof"},
Usage: "Parses hex eof container and returns validation errors (if any)",
Action: eofParseAction,
Flags: []cli.Flag{
hexFlag,
refTestFlag,
},
}
eofDumpCommand = &cli.Command{
Name: "eofdump",
Usage: "Parses hex eof container and prints out human-readable representation of the container.",
Action: eofDumpAction,
Flags: []cli.Flag{
hexFlag,
},
}
)
// vmFlags contains flags related to running the EVM.
var vmFlags = []cli.Flag{
CodeFlag,
CodeFileFlag,
CreateFlag,
GasFlag,
PriceFlag,
ValueFlag,
InputFlag,
InputFileFlag,
GenesisFlag,
SenderFlag,
ReceiverFlag,
}
// traceFlags contains flags that configure tracing output.
var traceFlags = []cli.Flag{
BenchFlag,
TraceFlag,
TraceFormatFlag,
TraceDisableStackFlag,
TraceDisableMemoryFlag,
TraceDisableStorageFlag,
TraceDisableReturnDataFlag,
// deprecated
DebugFlag,
DumpFlag,
MachineFlag,
StatDumpFlag,
DisableMemoryFlag,
DisableStackFlag,
DisableStorageFlag,
DisableReturnDataFlag,
}
var app = flags.NewApp("the evm command line interface")
func init() {
app.Flags = slices.Concat(vmFlags, traceFlags, debug.Flags)
app.Flags = debug.Flags
app.Commands = []*cli.Command{
compileCommand,
disasmCommand,
runCommand,
blockTestCommand,
stateTestCommand,
@ -280,11 +225,56 @@ func init() {
func main() {
if err := app.Run(os.Args); err != nil {
code := 1
if ec, ok := err.(*t8ntool.NumberedError); ok {
code = ec.ExitCode()
}
fmt.Fprintln(os.Stderr, err)
os.Exit(code)
os.Exit(1)
}
}
// tracerFromFlags parses the cli flags and returns the specified tracer.
func tracerFromFlags(ctx *cli.Context) *tracing.Hooks {
config := &logger.Config{
EnableMemory: !ctx.Bool(TraceDisableMemoryFlag.Name),
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
DisableStorage: ctx.Bool(TraceDisableStorageFlag.Name),
EnableReturnData: !ctx.Bool(TraceDisableReturnDataFlag.Name),
}
switch {
case ctx.Bool(TraceFlag.Name) && ctx.String(TraceFormatFlag.Name) == "struct":
return logger.NewStructLogger(config).Hooks()
case ctx.Bool(TraceFlag.Name) && ctx.String(TraceFormatFlag.Name) == "json":
return logger.NewJSONLogger(config, os.Stderr)
case ctx.Bool(MachineFlag.Name):
return logger.NewJSONLogger(config, os.Stderr)
case ctx.Bool(DebugFlag.Name):
return logger.NewStructLogger(config).Hooks()
default:
return nil
}
}
// collectJSONFiles walks the given path and accumulates all files with json
// extension.
func collectJSONFiles(path string) []string {
var out []string
err := filepath.Walk(path, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && filepath.Ext(info.Name()) == ".json" {
out = append(out, path)
}
return nil
})
if err != nil {
fmt.Fprintln(os.Stderr, err)
}
return out
}
// dump returns a state dump for the most current trie.
func dump(s *state.StateDB) *state.Dump {
root := s.IntermediateRoot(false)
cpy, _ := state.New(root, s.Database())
dump := cpy.RawDump(nil)
return &dump
}

87
cmd/evm/reporter.go Normal file
View File

@ -0,0 +1,87 @@
// Copyright 2024 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 (
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/urfave/cli/v2"
)
const (
PASS = "\033[32mPASS\033[0m"
FAIL = "\033[31mFAIL\033[0m"
)
// testResult contains the execution status after running a state test, any
// error that might have occurred and a dump of the final state if requested.
type testResult struct {
Name string `json:"name"`
Pass bool `json:"pass"`
Root *common.Hash `json:"stateRoot,omitempty"`
Fork string `json:"fork"`
Error string `json:"error,omitempty"`
State *state.Dump `json:"state,omitempty"`
Stats *execStats `json:"benchStats,omitempty"`
}
func (r testResult) String() string {
var status string
if r.Pass {
status = fmt.Sprintf("[%s]", PASS)
} else {
status = fmt.Sprintf("[%s]", FAIL)
}
info := r.Name
m := parseTestMetadata(r.Name)
if m != nil {
info = fmt.Sprintf("%s %s, param=%s", m.module, m.function, m.parameters)
}
var extra string
if !r.Pass {
extra = fmt.Sprintf(", err=%v, fork=%s", r.Error, r.Fork)
}
out := fmt.Sprintf("%s %s%s", status, info, extra)
if r.State != nil {
state, _ := json.MarshalIndent(r.State, "", " ")
out += "\n" + string(state)
}
return out
}
// report prints the after-test summary.
func report(ctx *cli.Context, results []testResult) {
if ctx.Bool(HumanReadableFlag.Name) {
pass := 0
for _, r := range results {
if r.Pass {
pass++
}
}
for _, r := range results {
fmt.Println(r)
}
fmt.Println("--")
fmt.Printf("%d tests passed, %d tests failed.\n", pass, len(results)-pass)
return
}
out, _ := json.MarshalIndent(results, "", " ")
fmt.Println(string(out))
}

View File

@ -25,10 +25,10 @@ import (
"os"
goruntime "runtime"
"slices"
"strings"
"testing"
"time"
"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
@ -51,14 +51,82 @@ var runCommand = &cli.Command{
Usage: "Run arbitrary evm binary",
ArgsUsage: "<code>",
Description: `The run command runs arbitrary EVM code.`,
Flags: slices.Concat(vmFlags, traceFlags),
Flags: slices.Concat([]cli.Flag{
BenchFlag,
CodeFileFlag,
CreateFlag,
GasFlag,
GenesisFlag,
InputFlag,
InputFileFlag,
PriceFlag,
ReceiverFlag,
SenderFlag,
ValueFlag,
StatDumpFlag,
}, traceFlags),
}
var (
CodeFileFlag = &cli.StringFlag{
Name: "codefile",
Usage: "File containing EVM code. If '-' is specified, code is read from stdin ",
Category: flags.VMCategory,
}
CreateFlag = &cli.BoolFlag{
Name: "create",
Usage: "Indicates the action should be create rather than call",
Category: flags.VMCategory,
}
GasFlag = &cli.Uint64Flag{
Name: "gas",
Usage: "Gas limit for the evm",
Value: 10000000000,
Category: flags.VMCategory,
}
GenesisFlag = &cli.StringFlag{
Name: "prestate",
Usage: "JSON file with prestate (genesis) config",
Category: flags.VMCategory,
}
InputFlag = &cli.StringFlag{
Name: "input",
Usage: "Input for the EVM",
Category: flags.VMCategory,
}
InputFileFlag = &cli.StringFlag{
Name: "inputfile",
Usage: "File containing input for the EVM",
Category: flags.VMCategory,
}
PriceFlag = &flags.BigFlag{
Name: "price",
Usage: "Price set for the evm",
Value: new(big.Int),
Category: flags.VMCategory,
}
ReceiverFlag = &cli.StringFlag{
Name: "receiver",
Usage: "The transaction receiver (execution context)",
Category: flags.VMCategory,
}
SenderFlag = &cli.StringFlag{
Name: "sender",
Usage: "The transaction origin",
Category: flags.VMCategory,
}
ValueFlag = &flags.BigFlag{
Name: "value",
Usage: "Value set for the evm",
Value: new(big.Int),
Category: flags.VMCategory,
}
)
// readGenesis will read the given JSON format genesis file and return
// the initialized Genesis structure
func readGenesis(genesisPath string) *core.Genesis {
// Make sure we have a valid genesis JSON
//genesisPath := ctx.Args().First()
if len(genesisPath) == 0 {
utils.Fatalf("Must supply path to genesis JSON file")
}
@ -128,10 +196,10 @@ func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) ([]byte, exe
func runCmd(ctx *cli.Context) error {
logconfig := &logger.Config{
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
DisableStack: ctx.Bool(DisableStackFlag.Name),
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
EnableMemory: !ctx.Bool(TraceDisableMemoryFlag.Name),
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
DisableStorage: ctx.Bool(TraceDisableStorageFlag.Name),
EnableReturnData: !ctx.Bool(TraceDisableReturnDataFlag.Name),
Debug: ctx.Bool(DebugFlag.Name),
}
@ -188,48 +256,35 @@ func runCmd(ctx *cli.Context) error {
var code []byte
codeFileFlag := ctx.String(CodeFileFlag.Name)
codeFlag := ctx.String(CodeFlag.Name)
hexcode := ctx.Args().First()
// The '--code' or '--codefile' flag overrides code in state
if codeFileFlag != "" || codeFlag != "" {
var hexcode []byte
if codeFileFlag != "" {
var err error
// If - is specified, it means that code comes from stdin
if codeFileFlag == "-" {
//Try reading from stdin
if hexcode, err = io.ReadAll(os.Stdin); err != nil {
fmt.Printf("Could not load code from stdin: %v\n", err)
os.Exit(1)
}
} else {
// Codefile with hex assembly
if hexcode, err = os.ReadFile(codeFileFlag); err != nil {
fmt.Printf("Could not load code from file: %v\n", err)
os.Exit(1)
}
}
} else {
hexcode = []byte(codeFlag)
}
hexcode = bytes.TrimSpace(hexcode)
if len(hexcode)%2 != 0 {
fmt.Printf("Invalid input length for hex data (%d)\n", len(hexcode))
// The '--codefile' flag overrides code in state
if codeFileFlag == "-" {
// If - is specified, it means that code comes from stdin
// Try reading from stdin
input, err := io.ReadAll(os.Stdin)
if err != nil {
fmt.Printf("Could not load code from stdin: %v\n", err)
os.Exit(1)
}
code = common.FromHex(string(hexcode))
} else if fn := ctx.Args().First(); len(fn) > 0 {
// EASM-file to compile
src, err := os.ReadFile(fn)
hexcode = string(input)
} else if codeFileFlag != "" {
// Codefile with hex assembly
input, err := os.ReadFile(codeFileFlag)
if err != nil {
return err
fmt.Printf("Could not load code from file: %v\n", err)
os.Exit(1)
}
bin, err := compiler.Compile(fn, src, false)
if err != nil {
return err
}
code = common.Hex2Bytes(bin)
hexcode = string(input)
}
hexcode = strings.TrimSpace(hexcode)
if len(hexcode)%2 != 0 {
fmt.Printf("Invalid input length for hex data (%d)\n", len(hexcode))
os.Exit(1)
}
code = common.FromHex(hexcode)
runtimeConfig := runtime.Config{
Origin: sender,
State: prestate,

View File

@ -21,12 +21,12 @@ import (
"encoding/json"
"fmt"
"os"
"regexp"
"slices"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/tests"
"github.com/urfave/cli/v2"
@ -35,157 +35,124 @@ import (
var (
forkFlag = &cli.StringFlag{
Name: "statetest.fork",
Usage: "The hard-fork to run the test against",
Usage: "Only run tests for the specified fork.",
Category: flags.VMCategory,
}
idxFlag = &cli.IntFlag{
Name: "statetest.index",
Usage: "The index of the subtest to run",
Usage: "The index of the subtest to run.",
Category: flags.VMCategory,
Value: -1, // default to select all subtest indices
}
testNameFlag = &cli.StringFlag{
Name: "statetest.name",
Usage: "The name of the state test to run",
Category: flags.VMCategory,
}
)
var stateTestCommand = &cli.Command{
Action: stateTestCmd,
Name: "statetest",
Usage: "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).",
ArgsUsage: "<file>",
Flags: []cli.Flag{
forkFlag,
idxFlag,
testNameFlag,
},
}
// StatetestResult contains the execution status after running a state test, any
// error that might have occurred and a dump of the final state if requested.
type StatetestResult struct {
Name string `json:"name"`
Pass bool `json:"pass"`
Root *common.Hash `json:"stateRoot,omitempty"`
Fork string `json:"fork"`
Error string `json:"error,omitempty"`
State *state.Dump `json:"state,omitempty"`
BenchStats *execStats `json:"benchStats,omitempty"`
Flags: slices.Concat([]cli.Flag{
DumpFlag,
HumanReadableFlag,
RunFlag,
}, traceFlags),
}
func stateTestCmd(ctx *cli.Context) error {
// Configure the EVM logger
config := &logger.Config{
EnableMemory: !ctx.Bool(DisableMemoryFlag.Name),
DisableStack: ctx.Bool(DisableStackFlag.Name),
DisableStorage: ctx.Bool(DisableStorageFlag.Name),
EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
}
var cfg vm.Config
switch {
case ctx.Bool(MachineFlag.Name):
cfg.Tracer = logger.NewJSONLogger(config, os.Stderr)
path := ctx.Args().First()
case ctx.Bool(DebugFlag.Name):
cfg.Tracer = logger.NewStructLogger(config).Hooks()
// If path is provided, run the tests at that path.
if len(path) != 0 {
var (
collected = collectJSONFiles(path)
results []testResult
)
for _, fname := range collected {
r, err := runStateTest(ctx, fname)
if err != nil {
return err
}
results = append(results, r...)
}
report(ctx, results)
return nil
}
// Load the test content from the input file
if len(ctx.Args().First()) != 0 {
return runStateTest(ctx, ctx.Args().First(), cfg, ctx.Bool(DumpFlag.Name), ctx.Bool(BenchFlag.Name))
}
// Read filenames from stdin and execute back-to-back
// 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
}
if err := runStateTest(ctx, fname, cfg, ctx.Bool(DumpFlag.Name), ctx.Bool(BenchFlag.Name)); err != nil {
results, err := runStateTest(ctx, fname)
if err != nil {
return err
}
report(ctx, results)
}
return nil
}
type stateTestCase struct {
name string
test tests.StateTest
st tests.StateSubtest
}
// collectMatchedSubtests returns test cases which match against provided filtering CLI parameters
func collectMatchedSubtests(ctx *cli.Context, testsByName map[string]tests.StateTest) []stateTestCase {
var res []stateTestCase
subtestName := ctx.String(testNameFlag.Name)
if subtestName != "" {
if subtest, ok := testsByName[subtestName]; ok {
testsByName := make(map[string]tests.StateTest)
testsByName[subtestName] = subtest
}
}
idx := ctx.Int(idxFlag.Name)
fork := ctx.String(forkFlag.Name)
for key, test := range testsByName {
for _, st := range test.Subtests() {
if idx != -1 && st.Index != idx {
continue
}
if fork != "" && st.Fork != fork {
continue
}
res = append(res, stateTestCase{name: key, st: st, test: test})
}
}
return res
}
// runStateTest loads the state-test given by fname, and executes the test.
func runStateTest(ctx *cli.Context, fname string, cfg vm.Config, dump bool, bench bool) error {
func runStateTest(ctx *cli.Context, fname string) ([]testResult, error) {
src, err := os.ReadFile(fname)
if err != nil {
return err
return nil, err
}
var testsByName map[string]tests.StateTest
if err := json.Unmarshal(src, &testsByName); err != nil {
return err
return nil, fmt.Errorf("unable to read test file %s: %w", fname, err)
}
matchingTests := collectMatchedSubtests(ctx, testsByName)
cfg := vm.Config{Tracer: tracerFromFlags(ctx)}
re, err := regexp.Compile(ctx.String(RunFlag.Name))
if err != nil {
return nil, fmt.Errorf("invalid regex -%s: %v", RunFlag.Name, err)
}
// Iterate over all the tests, run them and aggregate the results
var results []StatetestResult
for _, test := range matchingTests {
// Run the test and aggregate the result
result := &StatetestResult{Name: test.name, Fork: test.st.Fork, Pass: true}
test.test.Run(test.st, cfg, false, rawdb.HashScheme, func(err error, tstate *tests.StateTestState) {
var root common.Hash
if tstate.StateDB != nil {
root = tstate.StateDB.IntermediateRoot(false)
result.Root = &root
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
if dump { // Dump any state to aid debugging
cpy, _ := state.New(root, tstate.StateDB.Database())
dump := cpy.RawDump(nil)
result.State = &dump
}
}
if err != nil {
// Test failed, mark as so
result.Pass, result.Error = false, err.Error()
}
})
if bench {
_, stats, _ := timedExec(true, func() ([]byte, uint64, error) {
_, _, gasUsed, _ := test.test.RunNoVerify(test.st, cfg, false, rawdb.HashScheme)
return nil, gasUsed, nil
})
result.BenchStats = &stats
results := make([]testResult, 0, len(testsByName))
for key, test := range testsByName {
if !re.MatchString(key) {
continue
}
for i, st := range test.Subtests() {
if idx := ctx.Int(idxFlag.Name); idx != -1 && idx != i {
// If specific index requested, skip all tests that do not match.
continue
}
if fork := ctx.String(forkFlag.Name); fork != "" && st.Fork != fork {
// If specific fork requested, skip all tests that do not match.
continue
}
// Run the test and aggregate the result
result := &testResult{Name: key, Fork: st.Fork, Pass: true}
test.Run(st, cfg, false, rawdb.HashScheme, func(err error, state *tests.StateTestState) {
var root common.Hash
if state.StateDB != nil {
root = state.StateDB.IntermediateRoot(false)
result.Root = &root
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
// Dump any state to aid debugging.
if ctx.Bool(DumpFlag.Name) {
result.State = dump(state.StateDB)
}
}
// Collect bench stats if requested.
if ctx.Bool(BenchFlag.Name) {
_, stats, _ := timedExec(true, func() ([]byte, uint64, error) {
_, _, gasUsed, _ := test.RunNoVerify(st, cfg, false, rawdb.HashScheme)
return nil, gasUsed, nil
})
result.Stats = &stats
}
if err != nil {
// Test failed, mark as so.
result.Pass, result.Error = false, err.Error()
return
}
})
results = append(results, *result)
}
results = append(results, *result)
}
out, _ := json.MarshalIndent(results, "", " ")
fmt.Println(string(out))
return nil
return results, nil
}

View File

@ -50,7 +50,6 @@ import (
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/catalyst"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/eth/gasprice"
@ -1606,7 +1605,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
godebug.SetGCPercent(int(gogc))
if ctx.IsSet(SyncTargetFlag.Name) {
cfg.SyncMode = downloader.FullSync // dev sync target forces full sync
cfg.SyncMode = ethconfig.FullSync // dev sync target forces full sync
} else if ctx.IsSet(SyncModeFlag.Name) {
if err = cfg.SyncMode.UnmarshalText([]byte(ctx.String(SyncModeFlag.Name))); err != nil {
Fatalf("invalid --syncmode flag: %v", err)
@ -1677,7 +1676,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
}
if !ctx.Bool(SnapshotFlag.Name) || cfg.SnapshotCache == 0 {
// If snap-sync is requested, this flag is also required
if cfg.SyncMode == downloader.SnapSync {
if cfg.SyncMode == ethconfig.SnapSync {
if !ctx.Bool(SnapshotFlag.Name) {
log.Warn("Snap sync requested, enabling --snapshot")
}
@ -1743,7 +1742,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if !ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = 1337
}
cfg.SyncMode = downloader.FullSync
cfg.SyncMode = ethconfig.FullSync
// Create new developer account or reuse existing one
var (
developer accounts.Account

View File

@ -1926,7 +1926,7 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s
task := types.NewBlockWithHeader(context).WithBody(*block.Body())
// Run the stateless self-cross-validation
crossStateRoot, crossReceiptRoot, err := ExecuteStateless(bc.chainConfig, task, witness)
crossStateRoot, crossReceiptRoot, err := ExecuteStateless(bc.chainConfig, bc.vmConfig, task, witness)
if err != nil {
return nil, fmt.Errorf("stateless self-validation failed: %v", err)
}

View File

@ -40,7 +40,7 @@ import (
// - It cannot be placed outside of core, because it needs to construct a dud headerchain
//
// TODO(karalabe): Would be nice to resolve both issues above somehow and move it.
func ExecuteStateless(config *params.ChainConfig, block *types.Block, witness *stateless.Witness) (common.Hash, common.Hash, error) {
func ExecuteStateless(config *params.ChainConfig, vmconfig vm.Config, block *types.Block, witness *stateless.Witness) (common.Hash, common.Hash, error) {
// Sanity check if the supplied block accidentally contains a set root or
// receipt hash. If so, be very loud, but still continue.
if block.Root() != (common.Hash{}) {
@ -66,7 +66,7 @@ func ExecuteStateless(config *params.ChainConfig, block *types.Block, witness *s
validator := NewBlockValidator(config, nil) // No chain, we only validate the state, not the block
// Run the stateless blocks processing and self-validate certain fields
res, err := processor.Process(block, db, vm.Config{})
res, err := processor.Process(block, db, vmconfig)
if err != nil {
return common.Hash{}, common.Hash{}, err
}

View File

@ -424,17 +424,17 @@ func (s *Ethereum) Stop() error {
// SyncMode retrieves the current sync mode, either explicitly set, or derived
// from the chain status.
func (s *Ethereum) SyncMode() downloader.SyncMode {
func (s *Ethereum) SyncMode() ethconfig.SyncMode {
// If we're in snap sync mode, return that directly
if s.handler.snapSync.Load() {
return downloader.SnapSync
return ethconfig.SnapSync
}
// We are probably in full sync, but we might have rewound to before the
// snap sync pivot, check if we should re-enable snap sync.
head := s.blockchain.CurrentBlock()
if pivot := rawdb.ReadLastPivotNumber(s.chainDb); pivot != nil {
if head.Number.Uint64() < *pivot {
return downloader.SnapSync
return ethconfig.SnapSync
}
}
// We are in a full sync, but the associated head state is missing. To complete
@ -442,8 +442,8 @@ func (s *Ethereum) SyncMode() downloader.SyncMode {
// persistent state is corrupted, just mismatch with the head block.
if !s.blockchain.HasState(head.Root) {
log.Info("Reenabled snap sync as chain is stateless")
return downloader.SnapSync
return ethconfig.SnapSync
}
// Nope, we're really full syncing
return downloader.FullSync
return ethconfig.FullSync
}

View File

@ -31,8 +31,9 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/stateless"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner"
@ -917,7 +918,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
// tries to make it import a block. That should be denied as pushing something
// into the database directly will conflict with the assumptions of snap sync
// that it has an empty db that it can fill itself.
if api.eth.SyncMode() != downloader.FullSync {
if api.eth.SyncMode() != ethconfig.FullSync {
return api.delayPayloadImport(block), nil
}
if !api.eth.BlockChain().HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
@ -995,7 +996,7 @@ func (api *ConsensusAPI) executeStatelessPayload(params engine.ExecutableData, v
api.lastNewPayloadLock.Unlock()
log.Trace("Executing block statelessly", "number", block.Number(), "hash", params.BlockHash)
stateRoot, receiptRoot, err := core.ExecuteStateless(api.eth.BlockChain().Config(), block, witness)
stateRoot, receiptRoot, err := core.ExecuteStateless(api.eth.BlockChain().Config(), vm.Config{}, block, witness)
if err != nil {
log.Warn("ExecuteStatelessPayload: execution failed", "err", err)
errorMsg := err.Error()
@ -1030,7 +1031,7 @@ func (api *ConsensusAPI) delayPayloadImport(block *types.Block) engine.PayloadSt
// payload as non-integratable on top of the existing sync. We'll just
// have to rely on the beacon client to forcefully update the head with
// a forkchoice update request.
if api.eth.SyncMode() == downloader.FullSync {
if api.eth.SyncMode() == ethconfig.FullSync {
// In full sync mode, failure to import a well-formed block can only mean
// that the parent state is missing and the syncer rejected extending the
// current cycle with the new payload.

View File

@ -40,7 +40,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/miner"
@ -452,7 +451,7 @@ func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block)
}
mcfg := miner.DefaultConfig
ethcfg := &ethconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: mcfg}
ethcfg := &ethconfig.Config{Genesis: genesis, SyncMode: ethconfig.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: mcfg}
ethservice, err := eth.New(n, ethcfg)
if err != nil {
t.Fatal("can't create eth service:", err)

View File

@ -27,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/node"
@ -49,7 +48,7 @@ func startSimulatedBeaconEthService(t *testing.T, genesis *core.Genesis, period
t.Fatal("can't create node:", err)
}
ethcfg := &ethconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: miner.DefaultConfig}
ethcfg := &ethconfig.Config{Genesis: genesis, SyncMode: ethconfig.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: miner.DefaultConfig}
ethservice, err := eth.New(n, ethcfg)
if err != nil {
t.Fatal("can't create eth service:", err)

View File

@ -22,7 +22,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
)
@ -62,7 +62,7 @@ func (tester *FullSyncTester) Start() error {
// Trigger beacon sync with the provided block hash as trusted
// chain head.
err := tester.backend.Downloader().BeaconDevSync(downloader.FullSync, tester.target, tester.closed)
err := tester.backend.Downloader().BeaconDevSync(ethconfig.FullSync, tester.target, tester.closed)
if err != nil {
log.Info("Failed to trigger beacon sync", "err", err)
}

View File

@ -24,6 +24,7 @@ import (
"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/eth/ethconfig"
"github.com/ethereum/go-ethereum/log"
)
@ -198,9 +199,9 @@ func (d *Downloader) findBeaconAncestor() (uint64, error) {
var chainHead *types.Header
switch d.getMode() {
case FullSync:
case ethconfig.FullSync:
chainHead = d.blockchain.CurrentBlock()
case SnapSync:
case ethconfig.SnapSync:
chainHead = d.blockchain.CurrentSnapBlock()
default:
panic("unknown sync mode")
@ -218,9 +219,9 @@ func (d *Downloader) findBeaconAncestor() (uint64, error) {
}
var linked bool
switch d.getMode() {
case FullSync:
case ethconfig.FullSync:
linked = d.blockchain.HasBlock(beaconTail.ParentHash, beaconTail.Number.Uint64()-1)
case SnapSync:
case ethconfig.SnapSync:
linked = d.blockchain.HasFastBlock(beaconTail.ParentHash, beaconTail.Number.Uint64()-1)
default:
panic("unknown sync mode")
@ -253,9 +254,9 @@ func (d *Downloader) findBeaconAncestor() (uint64, error) {
var known bool
switch d.getMode() {
case FullSync:
case ethconfig.FullSync:
known = d.blockchain.HasBlock(h.Hash(), n)
case SnapSync:
case ethconfig.SnapSync:
known = d.blockchain.HasFastBlock(h.Hash(), n)
default:
panic("unknown sync mode")

View File

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/protocols/snap"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
@ -69,6 +70,17 @@ var (
errNoPivotHeader = errors.New("pivot header is not found")
)
// SyncMode defines the sync method of the downloader.
// Deprecated: use ethconfig.SyncMode instead
type SyncMode = ethconfig.SyncMode
const (
// Deprecated: use ethconfig.FullSync
FullSync = ethconfig.FullSync
// Deprecated: use ethconfig.SnapSync
SnapSync = ethconfig.SnapSync
)
// peerDropFn is a callback type for dropping a peer detected as malicious.
type peerDropFn func(id string)
@ -230,9 +242,9 @@ func (d *Downloader) Progress() ethereum.SyncProgress {
current := uint64(0)
mode := d.getMode()
switch mode {
case FullSync:
case ethconfig.FullSync:
current = d.blockchain.CurrentBlock().Number.Uint64()
case SnapSync:
case ethconfig.SnapSync:
current = d.blockchain.CurrentSnapBlock().Number.Uint64()
default:
log.Error("Unknown downloader mode", "mode", mode)
@ -326,7 +338,7 @@ func (d *Downloader) synchronise(mode SyncMode, beaconPing chan struct{}) error
if d.notified.CompareAndSwap(false, true) {
log.Info("Block synchronisation started")
}
if mode == SnapSync {
if mode == ethconfig.SnapSync {
// Snap sync will directly modify the persistent state, making the entire
// trie database unusable until the state is fully synced. To prevent any
// subsequent state reads, explicitly disable the trie database and state
@ -434,7 +446,7 @@ func (d *Downloader) syncToHead() (err error) {
// threshold (i.e. new chain). In that case we won't really snap sync
// anyway, but still need a valid pivot block to avoid some code hitting
// nil panics on access.
if mode == SnapSync && pivot == nil {
if mode == ethconfig.SnapSync && pivot == nil {
pivot = d.blockchain.CurrentBlock()
}
height := latest.Number.Uint64()
@ -452,7 +464,7 @@ func (d *Downloader) syncToHead() (err error) {
d.syncStatsLock.Unlock()
// Ensure our origin point is below any snap sync pivot point
if mode == SnapSync {
if mode == ethconfig.SnapSync {
if height <= uint64(fsMinFullBlocks) {
origin = 0
} else {
@ -466,10 +478,10 @@ func (d *Downloader) syncToHead() (err error) {
}
}
d.committed.Store(true)
if mode == SnapSync && pivot.Number.Uint64() != 0 {
if mode == ethconfig.SnapSync && pivot.Number.Uint64() != 0 {
d.committed.Store(false)
}
if mode == SnapSync {
if mode == ethconfig.SnapSync {
// Set the ancient data limitation. If we are running snap sync, all block
// data older than ancientLimit will be written to the ancient store. More
// recent data will be written to the active database and will wait for the
@ -523,13 +535,13 @@ func (d *Downloader) syncToHead() (err error) {
func() error { return d.fetchReceipts(origin + 1) }, // Receipts are retrieved during snap sync
func() error { return d.processHeaders(origin + 1) },
}
if mode == SnapSync {
if mode == ethconfig.SnapSync {
d.pivotLock.Lock()
d.pivotHeader = pivot
d.pivotLock.Unlock()
fetchers = append(fetchers, func() error { return d.processSnapSyncContent() })
} else if mode == FullSync {
} else if mode == ethconfig.FullSync {
fetchers = append(fetchers, func() error { return d.processFullSyncContent() })
}
return d.spawnSync(fetchers)
@ -676,7 +688,7 @@ func (d *Downloader) processHeaders(origin uint64) error {
chunkHashes := hashes[:limit]
// In case of header only syncing, validate the chunk immediately
if mode == SnapSync {
if mode == ethconfig.SnapSync {
// Although the received headers might be all valid, a legacy
// PoW/PoA sync must not accept post-merge headers. Make sure
// that any transition is rejected at this point.

View File

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/common/prque"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
@ -180,7 +181,7 @@ func (q *queue) Reset(blockCacheLimit int, thresholdInitialSize int) {
defer q.lock.Unlock()
q.closed = false
q.mode = FullSync
q.mode = ethconfig.FullSync
q.headerHead = common.Hash{}
q.headerPendPool = make(map[string]*fetchRequest)
@ -328,7 +329,7 @@ func (q *queue) Schedule(headers []*types.Header, hashes []common.Hash, from uin
q.blockTaskQueue.Push(header, -int64(header.Number.Uint64()))
}
// Queue for receipt retrieval
if q.mode == SnapSync && !header.EmptyReceipts() {
if q.mode == ethconfig.SnapSync && !header.EmptyReceipts() {
if _, ok := q.receiptTaskPool[hash]; ok {
log.Warn("Header already scheduled for receipt fetch", "number", header.Number, "hash", hash)
} else {
@ -523,7 +524,7 @@ func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common
// we can ask the resultcache if this header is within the
// "prioritized" segment of blocks. If it is not, we need to throttle
stale, throttle, item, err := q.resultCache.AddFetch(header, q.mode == SnapSync)
stale, throttle, item, err := q.resultCache.AddFetch(header, q.mode == ethconfig.SnapSync)
if stale {
// Don't put back in the task queue, this item has already been
// delivered upstream

View File

@ -29,7 +29,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
@ -49,7 +48,7 @@ var FullNodeGPO = gasprice.Config{
// Defaults contains default settings for use on the Ethereum main net.
var Defaults = Config{
SyncMode: downloader.SnapSync,
SyncMode: SnapSync,
NetworkId: 0, // enable auto configuration of networkID == chainID
TxLookupLimit: 2350000,
TransactionHistory: 2350000,
@ -80,7 +79,7 @@ type Config struct {
// Network ID separates blockchains on the peer-to-peer networking level. When left
// zero, the chain ID is used as network ID.
NetworkId uint64
SyncMode downloader.SyncMode
SyncMode SyncMode
// This can be set to list of enrtree:// URLs which will be queried for
// nodes to connect to.

View File

@ -9,7 +9,6 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/miner"
)
@ -19,7 +18,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
type Config struct {
Genesis *core.Genesis `toml:",omitempty"`
NetworkId uint64
SyncMode downloader.SyncMode
SyncMode SyncMode
EthDiscoveryURLs []string
SnapDiscoveryURLs []string
NoPruning bool
@ -95,7 +94,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
type Config struct {
Genesis *core.Genesis `toml:",omitempty"`
NetworkId *uint64
SyncMode *downloader.SyncMode
SyncMode *SyncMode
EthDiscoveryURLs []string
SnapDiscoveryURLs []string
NoPruning *bool

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package downloader
package ethconfig
import "fmt"

View File

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/fetcher"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/eth/protocols/snap"
@ -87,7 +88,7 @@ type handlerConfig struct {
Chain *core.BlockChain // Blockchain to serve data from
TxPool txPool // Transaction pool to propagate from
Network uint64 // Network identifier to advertise
Sync downloader.SyncMode // Whether to snap or full sync
Sync ethconfig.SyncMode // Whether to snap or full sync
BloomCache uint64 // Megabytes to alloc for snap sync bloom
EventMux *event.TypeMux // Legacy event mux, deprecate for `feed`
RequiredBlocks map[uint64]common.Hash // Hard coded map of required block hashes for sync challenges
@ -145,7 +146,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
handlerDoneCh: make(chan struct{}),
handlerStartCh: make(chan struct{}),
}
if config.Sync == downloader.FullSync {
if config.Sync == ethconfig.FullSync {
// The database seems empty as the current block is the genesis. Yet the snap
// block is ahead, so snap sync was enabled for this node at a certain point.
// The scenarios where this can happen is

View File

@ -29,7 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
@ -109,7 +109,7 @@ func testForkIDSplit(t *testing.T, protocol uint) {
Chain: chainNoFork,
TxPool: newTestTxPool(),
Network: 1,
Sync: downloader.FullSync,
Sync: ethconfig.FullSync,
BloomCache: 1,
})
ethProFork, _ = newHandler(&handlerConfig{
@ -117,7 +117,7 @@ func testForkIDSplit(t *testing.T, protocol uint) {
Chain: chainProFork,
TxPool: newTestTxPool(),
Network: 1,
Sync: downloader.FullSync,
Sync: ethconfig.FullSync,
BloomCache: 1,
})
)

View File

@ -29,7 +29,7 @@ import (
"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/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
@ -164,7 +164,7 @@ func newTestHandlerWithBlocks(blocks int) *testHandler {
Chain: chain,
TxPool: txpool,
Network: 1,
Sync: downloader.SnapSync,
Sync: ethconfig.SnapSync,
BloomCache: 1,
})
handler.Start(1000)

View File

@ -20,7 +20,7 @@ import (
"testing"
"time"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/eth/protocols/snap"
"github.com/ethereum/go-ethereum/p2p"
@ -85,7 +85,7 @@ func testSnapSyncDisabling(t *testing.T, ethVer uint, snapVer uint) {
time.Sleep(250 * time.Millisecond)
// Check that snap sync was disabled
if err := empty.handler.downloader.BeaconSync(downloader.SnapSync, full.chain.CurrentBlock(), nil); err != nil {
if err := empty.handler.downloader.BeaconSync(ethconfig.SnapSync, full.chain.CurrentBlock(), nil); err != nil {
t.Fatal("sync failed:", err)
}
empty.handler.enableSyncedFeatures()

View File

@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/catalyst"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/ethclient"
@ -85,7 +84,7 @@ func NewBackend(alloc types.GenesisAlloc, options ...func(nodeConf *node.Config,
GasLimit: ethconfig.Defaults.Miner.GasCeil,
Alloc: alloc,
}
ethConf.SyncMode = downloader.FullSync
ethConf.SyncMode = ethconfig.FullSync
ethConf.TxPool.NoLocals = true
for _, option := range options {

View File

@ -136,8 +136,8 @@ var (
Category: flags.LoggingCategory,
}
traceFlag = &cli.StringFlag{
Name: "trace",
Usage: "Write execution trace to the given file",
Name: "go-execution-trace",
Usage: "Write Go execution trace to the given file",
Category: flags.LoggingCategory,
}
)

View File

@ -234,10 +234,6 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/secp256k1 \
compile_fuzzer github.com/ethereum/go-ethereum/eth/protocols/eth \
FuzzEthProtocolHandlers fuzz_eth_protocol_handlers \
$repo/eth/protocols/eth/handler_test.go
$repo/eth/protocols/eth/handler_test.go,$repo/eth/protocols/eth/peer_test.go
#compile_fuzzer tests/fuzzers/vflux FuzzClientPool fuzzClientPool
#compile_fuzzer tests/fuzzers/difficulty Fuzz fuzzDifficulty
#compile_fuzzer tests/fuzzers/les Fuzz fuzzLes