github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/cmd/evm/staterunner.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:27</date> 10 //</624342590182920192> 11 12 13 package main 14 15 import ( 16 "encoding/json" 17 "errors" 18 "fmt" 19 "io/ioutil" 20 "os" 21 22 "github.com/ethereum/go-ethereum/core/state" 23 "github.com/ethereum/go-ethereum/core/vm" 24 "github.com/ethereum/go-ethereum/log" 25 "github.com/ethereum/go-ethereum/tests" 26 27 cli "gopkg.in/urfave/cli.v1" 28 ) 29 30 var stateTestCommand = cli.Command{ 31 Action: stateTestCmd, 32 Name: "statetest", 33 Usage: "executes the given state tests", 34 ArgsUsage: "<file>", 35 } 36 37 //StateTestResult包含运行状态测试后的执行状态,任何 38 //可能发生的错误和最终状态的转储(如果请求)。 39 type StatetestResult struct { 40 Name string `json:"name"` 41 Pass bool `json:"pass"` 42 Fork string `json:"fork"` 43 Error string `json:"error,omitempty"` 44 State *state.Dump `json:"state,omitempty"` 45 } 46 47 func stateTestCmd(ctx *cli.Context) error { 48 if len(ctx.Args().First()) == 0 { 49 return errors.New("path-to-test argument required") 50 } 51 //配置Go以太坊记录器 52 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 53 glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) 54 log.Root().SetHandler(glogger) 55 56 //配置EVM记录器 57 config := &vm.LogConfig{ 58 DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), 59 DisableStack: ctx.GlobalBool(DisableStackFlag.Name), 60 } 61 var ( 62 tracer vm.Tracer 63 debugger *vm.StructLogger 64 ) 65 switch { 66 case ctx.GlobalBool(MachineFlag.Name): 67 tracer = NewJSONLogger(config, os.Stderr) 68 69 case ctx.GlobalBool(DebugFlag.Name): 70 debugger = vm.NewStructLogger(config) 71 tracer = debugger 72 73 default: 74 debugger = vm.NewStructLogger(config) 75 } 76 //从输入文件加载测试内容 77 src, err := ioutil.ReadFile(ctx.Args().First()) 78 if err != nil { 79 return err 80 } 81 var tests map[string]tests.StateTest 82 if err = json.Unmarshal(src, &tests); err != nil { 83 return err 84 } 85 //迭代所有测试,运行它们并聚合结果 86 cfg := vm.Config{ 87 Tracer: tracer, 88 Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), 89 } 90 results := make([]StatetestResult, 0, len(tests)) 91 for key, test := range tests { 92 for _, st := range test.Subtests() { 93 //运行测试并汇总结果 94 result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true} 95 state, err := test.Run(st, cfg) 96 if err != nil { 97 //测试失败,标记为“是”,并转储任何状态以帮助调试 98 result.Pass, result.Error = false, err.Error() 99 if ctx.GlobalBool(DumpFlag.Name) && state != nil { 100 dump := state.RawDump() 101 result.State = &dump 102 } 103 } 104 //打印evmlab跟踪的状态根(已在上面提交,因此无需再次删除对象 105 if ctx.GlobalBool(MachineFlag.Name) && state != nil { 106 fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%x\"}\n", state.IntermediateRoot(false)) 107 } 108 109 results = append(results, *result) 110 111 //打印收集的任何结构化日志 112 if ctx.GlobalBool(DebugFlag.Name) { 113 if debugger != nil { 114 fmt.Fprintln(os.Stderr, "#### TRACE ####") 115 vm.WriteTrace(os.Stderr, debugger.StructLogs()) 116 } 117 } 118 } 119 } 120 out, _ := json.MarshalIndent(results, "", " ") 121 fmt.Println(string(out)) 122 return nil 123 } 124