Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 58 additions & 13 deletions cmd/evm/blockrunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,50 +17,71 @@
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"
)

var blockTestCommand = &cli.Command{
Action: blockTestCmd,
Name: "blocktest",
Usage: "Executes the given blockchain tests",
Usage: "Executes the given blockchain tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).",
ArgsUsage: "<path>",
Flags: slices.Concat([]cli.Flag{
DumpFlag,
HumanReadableFlag,
RunFlag,
WitnessCrossCheckFlag,
FuzzFlag,
}, traceFlags),
}

func blockTestCmd(ctx *cli.Context) error {
path := ctx.Args().First()
if len(path) == 0 {
return errors.New("path argument required")

// 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
}
var (
collected = collectFiles(path)
results []testResult
)
for _, fname := range collected {
r, err := runBlockTest(ctx, fname)
// 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)
if err != nil {
return err
}
results = append(results, r...)
// During fuzzing, we report the result after every block
if !ctx.IsSet(FuzzFlag.Name) {
report(ctx, results)
}
}
report(ctx, results)
return nil
}

Expand All @@ -79,6 +100,11 @@ 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))

Expand All @@ -88,16 +114,35 @@ func runBlockTest(ctx *cli.Context, fname string) ([]testResult, error) {
if !re.MatchString(name) {
continue
}
test := tests[name]
result := &testResult{Name: name, Pass: true}
if err := tests[name].Run(false, rawdb.PathScheme, ctx.Bool(WitnessCrossCheckFlag.Name), tracer, func(res error, chain *core.BlockChain) {
var finalRoot *common.Hash
if err := test.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
Expand Down
5 changes: 5 additions & 0 deletions cmd/evm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ var (
Usage: "benchmark the execution",
Category: flags.VMCategory,
}
FuzzFlag = &cli.BoolFlag{
Name: "fuzz",
Usage: "adepts output format for fuzzing",
Category: flags.VMCategory,
}
WitnessCrossCheckFlag = &cli.BoolFlag{
Name: "cross-check",
Aliases: []string{"xc"},
Expand Down
11 changes: 10 additions & 1 deletion tests/block_test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
if !ok {
return UnsupportedForkError{t.json.Network}
}
return t.run(config, snapshotter, scheme, witness, tracer, postCheck)
}

// Network returns the network/fork name for this test.
func (t *BlockTest) Network() string {
return t.json.Network
}

func (t *BlockTest) run(config *params.ChainConfig, snapshotter bool, scheme string, witness bool, tracer *tracing.Hooks, postCheck func(error, *core.BlockChain)) (result error) {
// import pre accounts & construct test genesis block & state root
var (
db = rawdb.NewMemoryDatabase()
Expand Down Expand Up @@ -259,7 +268,7 @@ func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error)
}
if b.BlockHeader == nil {
if data, err := json.MarshalIndent(cb.Header(), "", " "); err == nil {
fmt.Fprintf(os.Stderr, "block (index %d) insertion should have failed due to: %v:\n%v\n",
fmt.Fprintf(os.Stdout, "block (index %d) insertion should have failed due to: %v:\n%v\n",
bi, b.ExpectException, string(data))
}
return nil, fmt.Errorf("block (index %d) insertion should have failed due to: %v",
Expand Down