github.com/jimmyx0x/go-ethereum@v1.10.28/cmd/evm/staterunner.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "encoding/json" 21 "errors" 22 "fmt" 23 "os" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/core/state" 27 "github.com/ethereum/go-ethereum/core/vm" 28 "github.com/ethereum/go-ethereum/eth/tracers/logger" 29 "github.com/ethereum/go-ethereum/log" 30 "github.com/ethereum/go-ethereum/tests" 31 "github.com/urfave/cli/v2" 32 ) 33 34 var stateTestCommand = &cli.Command{ 35 Action: stateTestCmd, 36 Name: "statetest", 37 Usage: "executes the given state tests", 38 ArgsUsage: "<file>", 39 } 40 41 // StatetestResult contains the execution status after running a state test, any 42 // error that might have occurred and a dump of the final state if requested. 43 type StatetestResult struct { 44 Name string `json:"name"` 45 Pass bool `json:"pass"` 46 Root *common.Hash `json:"stateRoot,omitempty"` 47 Fork string `json:"fork"` 48 Error string `json:"error,omitempty"` 49 State *state.Dump `json:"state,omitempty"` 50 } 51 52 func stateTestCmd(ctx *cli.Context) error { 53 if len(ctx.Args().First()) == 0 { 54 return errors.New("path-to-test argument required") 55 } 56 // Configure the go-ethereum logger 57 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 58 glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name))) 59 log.Root().SetHandler(glogger) 60 61 // Configure the EVM logger 62 config := &logger.Config{ 63 EnableMemory: !ctx.Bool(DisableMemoryFlag.Name), 64 DisableStack: ctx.Bool(DisableStackFlag.Name), 65 DisableStorage: ctx.Bool(DisableStorageFlag.Name), 66 EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name), 67 } 68 var ( 69 tracer vm.EVMLogger 70 debugger *logger.StructLogger 71 ) 72 switch { 73 case ctx.Bool(MachineFlag.Name): 74 tracer = logger.NewJSONLogger(config, os.Stderr) 75 76 case ctx.Bool(DebugFlag.Name): 77 debugger = logger.NewStructLogger(config) 78 tracer = debugger 79 80 default: 81 debugger = logger.NewStructLogger(config) 82 } 83 // Load the test content from the input file 84 src, err := os.ReadFile(ctx.Args().First()) 85 if err != nil { 86 return err 87 } 88 var tests map[string]tests.StateTest 89 if err = json.Unmarshal(src, &tests); err != nil { 90 return err 91 } 92 // Iterate over all the tests, run them and aggregate the results 93 cfg := vm.Config{ 94 Tracer: tracer, 95 Debug: ctx.Bool(DebugFlag.Name) || ctx.Bool(MachineFlag.Name), 96 } 97 results := make([]StatetestResult, 0, len(tests)) 98 for key, test := range tests { 99 for _, st := range test.Subtests() { 100 // Run the test and aggregate the result 101 result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true} 102 _, s, err := test.Run(st, cfg, false) 103 // print state root for evmlab tracing 104 if s != nil { 105 root := s.IntermediateRoot(false) 106 result.Root = &root 107 if ctx.Bool(MachineFlag.Name) { 108 fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root) 109 } 110 } 111 if err != nil { 112 // Test failed, mark as so and dump any state to aid debugging 113 result.Pass, result.Error = false, err.Error() 114 if ctx.Bool(DumpFlag.Name) && s != nil { 115 dump := s.RawDump(nil) 116 result.State = &dump 117 } 118 } 119 120 results = append(results, *result) 121 122 // Print any structured logs collected 123 if ctx.Bool(DebugFlag.Name) { 124 if debugger != nil { 125 fmt.Fprintln(os.Stderr, "#### TRACE ####") 126 logger.WriteTrace(os.Stderr, debugger.StructLogs()) 127 } 128 } 129 } 130 } 131 out, _ := json.MarshalIndent(results, "", " ") 132 fmt.Println(string(out)) 133 return nil 134 }