staterunner.go 3.9 KB

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