github.com/theQRL/go-zond@v0.1.1/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  	"bufio"
    21  	"encoding/json"
    22  	"fmt"
    23  	"os"
    24  
    25  	"github.com/theQRL/go-zond/common"
    26  	"github.com/theQRL/go-zond/core/rawdb"
    27  	"github.com/theQRL/go-zond/core/state"
    28  	"github.com/theQRL/go-zond/core/state/snapshot"
    29  	"github.com/theQRL/go-zond/core/vm"
    30  	"github.com/theQRL/go-zond/log"
    31  	"github.com/theQRL/go-zond/tests"
    32  	"github.com/theQRL/go-zond/zond/tracers/logger"
    33  	"github.com/urfave/cli/v2"
    34  )
    35  
    36  var stateTestCommand = &cli.Command{
    37  	Action:    stateTestCmd,
    38  	Name:      "statetest",
    39  	Usage:     "Executes the given state tests. Filenames can be fed via standard input (batch mode) or as an argument (one-off execution).",
    40  	ArgsUsage: "<file>",
    41  }
    42  
    43  // StatetestResult contains the execution status after running a state test, any
    44  // error that might have occurred and a dump of the final state if requested.
    45  type StatetestResult struct {
    46  	Name  string       `json:"name"`
    47  	Pass  bool         `json:"pass"`
    48  	Root  *common.Hash `json:"stateRoot,omitempty"`
    49  	Fork  string       `json:"fork"`
    50  	Error string       `json:"error,omitempty"`
    51  	State *state.Dump  `json:"state,omitempty"`
    52  }
    53  
    54  func stateTestCmd(ctx *cli.Context) error {
    55  	// Configure the go-ethereum logger
    56  	glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
    57  	glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
    58  	log.Root().SetHandler(glogger)
    59  
    60  	// Configure the EVM logger
    61  	config := &logger.Config{
    62  		EnableMemory:     !ctx.Bool(DisableMemoryFlag.Name),
    63  		DisableStack:     ctx.Bool(DisableStackFlag.Name),
    64  		DisableStorage:   ctx.Bool(DisableStorageFlag.Name),
    65  		EnableReturnData: !ctx.Bool(DisableReturnDataFlag.Name),
    66  	}
    67  	var cfg vm.Config
    68  	switch {
    69  	case ctx.Bool(MachineFlag.Name):
    70  		cfg.Tracer = logger.NewJSONLogger(config, os.Stderr)
    71  
    72  	case ctx.Bool(DebugFlag.Name):
    73  		cfg.Tracer = logger.NewStructLogger(config)
    74  	}
    75  	// Load the test content from the input file
    76  	if len(ctx.Args().First()) != 0 {
    77  		return runStateTest(ctx.Args().First(), cfg, ctx.Bool(MachineFlag.Name), ctx.Bool(DumpFlag.Name))
    78  	}
    79  	// Read filenames from stdin and execute back-to-back
    80  	scanner := bufio.NewScanner(os.Stdin)
    81  	for scanner.Scan() {
    82  		fname := scanner.Text()
    83  		if len(fname) == 0 {
    84  			return nil
    85  		}
    86  		if err := runStateTest(fname, cfg, ctx.Bool(MachineFlag.Name), ctx.Bool(DumpFlag.Name)); err != nil {
    87  			return err
    88  		}
    89  	}
    90  	return nil
    91  }
    92  
    93  // runStateTest loads the state-test given by fname, and executes the test.
    94  func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error {
    95  	src, err := os.ReadFile(fname)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	var tests map[string]tests.StateTest
   100  	if err := json.Unmarshal(src, &tests); err != nil {
   101  		return err
   102  	}
   103  	// Iterate over all the tests, run them and aggregate the results
   104  	results := make([]StatetestResult, 0, len(tests))
   105  	for key, test := range tests {
   106  		for _, st := range test.Subtests() {
   107  			// Run the test and aggregate the result
   108  			result := &StatetestResult{Name: key, Fork: st.Fork, Pass: true}
   109  			test.Run(st, cfg, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
   110  				if state != nil {
   111  					root := state.IntermediateRoot(false)
   112  					result.Root = &root
   113  					if jsonOut {
   114  						fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
   115  					}
   116  				}
   117  				if err != nil {
   118  					// Test failed, mark as so and dump any state to aid debugging
   119  					result.Pass, result.Error = false, err.Error()
   120  					if dump {
   121  						dump := state.RawDump(nil)
   122  						result.State = &dump
   123  					}
   124  				}
   125  			})
   126  			results = append(results, *result)
   127  		}
   128  	}
   129  	out, _ := json.MarshalIndent(results, "", "  ")
   130  	fmt.Println(string(out))
   131  	return nil
   132  }