mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 07:37:20 +00:00
This is broken off of #31730 to only focus on testing networks that start with verkle at genesis. The PR has seen a lot of work since its creation, and it now targets creating and re-executing tests for a binary tree testnet without the transition (so it starts at genesis). The transition tree has been moved to its own package. It also replaces verkle with the binary tree for this specific application. --------- Co-authored-by: Gary Rong <garyrong0905@gmail.com>
341 lines
9.1 KiB
Go
341 lines
9.1 KiB
Go
// Copyright 2014 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/>.
|
|
|
|
// evm executes EVM code snippets.
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"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"
|
|
|
|
// Force-load the tracer engines to trigger registration
|
|
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
|
_ "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 (
|
|
// 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,
|
|
}
|
|
WitnessCrossCheckFlag = &cli.BoolFlag{
|
|
Name: "cross-check",
|
|
Aliases: []string{"xc"},
|
|
Usage: "Cross-check stateful execution against stateless, verifying the witness generation.",
|
|
}
|
|
|
|
// 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 (json|struct|md)",
|
|
Value: "json",
|
|
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 (deprecated)",
|
|
Hidden: true,
|
|
Category: traceCategory,
|
|
}
|
|
)
|
|
|
|
// Command definitions.
|
|
var (
|
|
stateTransitionCommand = &cli.Command{
|
|
Name: "transition",
|
|
Aliases: []string{"t8n"},
|
|
Usage: "Executes a full state transition",
|
|
Action: t8ntool.Transition,
|
|
Flags: []cli.Flag{
|
|
t8ntool.TraceFlag,
|
|
t8ntool.TraceTracerFlag,
|
|
t8ntool.TraceTracerConfigFlag,
|
|
t8ntool.TraceEnableMemoryFlag,
|
|
t8ntool.TraceDisableStackFlag,
|
|
t8ntool.TraceEnableReturnDataFlag,
|
|
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,
|
|
},
|
|
}
|
|
|
|
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"},
|
|
Usage: "Performs transaction validation",
|
|
Action: t8ntool.Transaction,
|
|
Flags: []cli.Flag{
|
|
t8ntool.InputTxsFlag,
|
|
t8ntool.ChainIDFlag,
|
|
t8ntool.ForknameFlag,
|
|
},
|
|
}
|
|
|
|
blockBuilderCommand = &cli.Command{
|
|
Name: "block-builder",
|
|
Aliases: []string{"b11r"},
|
|
Usage: "Builds a block",
|
|
Action: t8ntool.BuildBlock,
|
|
Flags: []cli.Flag{
|
|
t8ntool.OutputBasedir,
|
|
t8ntool.OutputBlockFlag,
|
|
t8ntool.InputHeaderFlag,
|
|
t8ntool.InputOmmersFlag,
|
|
t8ntool.InputWithdrawalsFlag,
|
|
t8ntool.InputTxsRlpFlag,
|
|
t8ntool.SealCliqueFlag,
|
|
},
|
|
}
|
|
)
|
|
|
|
// traceFlags contains flags that configure tracing output.
|
|
var traceFlags = []cli.Flag{
|
|
TraceFlag,
|
|
TraceFormatFlag,
|
|
TraceDisableStackFlag,
|
|
TraceDisableMemoryFlag,
|
|
TraceDisableStorageFlag,
|
|
TraceDisableReturnDataFlag,
|
|
|
|
// deprecated
|
|
DebugFlag,
|
|
MachineFlag,
|
|
}
|
|
|
|
var app = flags.NewApp("the evm command line interface")
|
|
|
|
func init() {
|
|
app.Flags = debug.Flags
|
|
app.Commands = []*cli.Command{
|
|
runCommand,
|
|
blockTestCommand,
|
|
stateTestCommand,
|
|
stateTransitionCommand,
|
|
transactionCommand,
|
|
blockBuilderCommand,
|
|
verkleCommand,
|
|
}
|
|
app.Before = func(ctx *cli.Context) error {
|
|
flags.MigrateGlobalFlags(ctx)
|
|
return debug.Setup(ctx)
|
|
}
|
|
app.After = func(ctx *cli.Context) error {
|
|
debug.Exit()
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
if err := app.Run(os.Args); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
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):
|
|
switch format := ctx.String(TraceFormatFlag.Name); format {
|
|
case "struct":
|
|
return logger.NewStreamingStructLogger(config, os.Stderr).Hooks()
|
|
case "json":
|
|
return logger.NewJSONLogger(config, os.Stderr)
|
|
case "md", "markdown":
|
|
return logger.NewMarkdownLogger(config, os.Stderr).Hooks()
|
|
default:
|
|
fmt.Fprintf(os.Stderr, "unknown trace format: %q\n", format)
|
|
os.Exit(1)
|
|
return nil
|
|
}
|
|
// Deprecated ways of configuring tracing.
|
|
case ctx.Bool(MachineFlag.Name):
|
|
return logger.NewJSONLogger(config, os.Stderr)
|
|
case ctx.Bool(DebugFlag.Name):
|
|
return logger.NewStreamingStructLogger(config, os.Stderr).Hooks()
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// collectFiles walks the given path. If the path is a directory, it will
|
|
// return a list of all accumulates all files with json extension.
|
|
// Otherwise (if path points to a file), it will return the path.
|
|
func collectFiles(path string) []string {
|
|
var out []string
|
|
if info, err := os.Stat(path); err == nil && !info.IsDir() {
|
|
// User explicitly pointed out a file, ignore extension.
|
|
return []string{path}
|
|
}
|
|
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
|
|
}
|