github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/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 "io/ioutil" 24 "os" 25 26 "github.com/ethereum/go-ethereum/core/state" 27 "github.com/ethereum/go-ethereum/core/vm" 28 "github.com/ethereum/go-ethereum/log" 29 "github.com/ethereum/go-ethereum/tests" 30 cli "gopkg.in/urfave/cli.v1" 31 ) 32 33 var stateTestCommand = cli.Command{ 34 Action: stateTestCmd, 35 Name: "statetest", 36 Usage: "executes the given state tests", 37 ArgsUsage: "<file>", 38 } 39 40 // StatetestResult contains the execution status after running a state test, any 41 // error that might have occurred and a dump of the final state if requested. 42 type StatetestResult struct { 43 Name string `json:"name"` 44 Pass bool `json:"pass"` 45 Fork string `json:"fork"` 46 Error string `json:"error,omitempty"` 47 State *state.Dump `json:"state,omitempty"` 48 } 49 50 func stateTestCmd(ctx *cli.Context) error { 51 if len(ctx.Args().First()) == 0 { 52 return errors.New("path-to-test argument required") 53 } 54 // Configure the go-ethereum logger 55 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 56 glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) 57 log.Root().SetHandler(glogger) 58 59 // Configure the EVM logger 60 config := &vm.LogConfig{ 61 DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), 62 DisableStack: ctx.GlobalBool(DisableStackFlag.Name), 63 } 64 var ( 65 tracer vm.Tracer 66 debugger *vm.StructLogger 67 ) 68 switch { 69 case ctx.GlobalBool(MachineFlag.Name): 70 tracer = vm.NewJSONLogger(config, os.Stderr) 71 72 case ctx.GlobalBool(DebugFlag.Name): 73 debugger = vm.NewStructLogger(config) 74 tracer = debugger 75 76 default: 77 debugger = vm.NewStructLogger(config) 78 } 79 // Load the test content from the input file 80 src, err := ioutil.ReadFile(ctx.Args().First()) 81 if err != nil { 82 return err 83 } 84 var tests map[string]tests.StateTest 85 if err = json.Unmarshal(src, &tests); err != nil { 86 return err 87 } 88 // Iterate over all the tests, run them and aggregate the results 89 cfg := vm.Config{ 90 Tracer: tracer, 91 Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), 92 } 93 results := make([]StatetestResult, 0, len(tests)) 94 for key, test := range tests { 95 for _, st := range test.Subtests() { 96 // Run the test and aggregate the result 97 result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true} 98 state, err := test.Run(st, cfg) 99 // print state root for evmlab tracing 100 if ctx.GlobalBool(MachineFlag.Name) && state != nil { 101 fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", state.IntermediateRoot(false)) 102 } 103 if err != nil { 104 // Test failed, mark as so and dump any state to aid debugging 105 result.Pass, result.Error = false, err.Error() 106 if ctx.GlobalBool(DumpFlag.Name) && state != nil { 107 dump := state.RawDump() 108 result.State = &dump 109 } 110 } 111 112 results = append(results, *result) 113 114 // Print any structured logs collected 115 if ctx.GlobalBool(DebugFlag.Name) { 116 if debugger != nil { 117 fmt.Fprintln(os.Stderr, "#### TRACE ####") 118 vm.WriteTrace(os.Stderr, debugger.StructLogs()) 119 } 120 } 121 } 122 } 123 out, _ := json.MarshalIndent(results, "", " ") 124 fmt.Println(string(out)) 125 return nil 126 }