github.com/ylsgit/go-ethereum@v1.6.5/cmd/evm/runner.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 "bytes" 21 "fmt" 22 "io/ioutil" 23 "os" 24 "runtime/pprof" 25 "time" 26 27 goruntime "runtime" 28 29 "github.com/ethereum/go-ethereum/cmd/evm/internal/compiler" 30 "github.com/ethereum/go-ethereum/cmd/utils" 31 "github.com/ethereum/go-ethereum/common" 32 "github.com/ethereum/go-ethereum/core/state" 33 "github.com/ethereum/go-ethereum/core/vm" 34 "github.com/ethereum/go-ethereum/core/vm/runtime" 35 "github.com/ethereum/go-ethereum/ethdb" 36 "github.com/ethereum/go-ethereum/log" 37 cli "gopkg.in/urfave/cli.v1" 38 ) 39 40 var runCommand = cli.Command{ 41 Action: runCmd, 42 Name: "run", 43 Usage: "run arbitrary evm binary", 44 ArgsUsage: "<code>", 45 Description: `The run command runs arbitrary EVM code.`, 46 } 47 48 func runCmd(ctx *cli.Context) error { 49 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 50 glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) 51 log.Root().SetHandler(glogger) 52 53 var ( 54 db, _ = ethdb.NewMemDatabase() 55 statedb, _ = state.New(common.Hash{}, db) 56 sender = common.StringToAddress("sender") 57 logger = vm.NewStructLogger(nil) 58 ) 59 statedb.CreateAccount(sender) 60 61 var ( 62 code []byte 63 ret []byte 64 err error 65 ) 66 if fn := ctx.Args().First(); len(fn) > 0 { 67 src, err := ioutil.ReadFile(fn) 68 if err != nil { 69 return err 70 } 71 72 bin, err := compiler.Compile(fn, src, false) 73 if err != nil { 74 return err 75 } 76 code = common.Hex2Bytes(bin) 77 } else if ctx.GlobalString(CodeFlag.Name) != "" { 78 code = common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)) 79 } else { 80 var hexcode []byte 81 if ctx.GlobalString(CodeFileFlag.Name) != "" { 82 var err error 83 hexcode, err = ioutil.ReadFile(ctx.GlobalString(CodeFileFlag.Name)) 84 if err != nil { 85 fmt.Printf("Could not load code from file: %v\n", err) 86 os.Exit(1) 87 } 88 } else { 89 var err error 90 hexcode, err = ioutil.ReadAll(os.Stdin) 91 if err != nil { 92 fmt.Printf("Could not load code from stdin: %v\n", err) 93 os.Exit(1) 94 } 95 } 96 code = common.Hex2Bytes(string(bytes.TrimRight(hexcode, "\n"))) 97 } 98 99 runtimeConfig := runtime.Config{ 100 Origin: sender, 101 State: statedb, 102 GasLimit: ctx.GlobalUint64(GasFlag.Name), 103 GasPrice: utils.GlobalBig(ctx, PriceFlag.Name), 104 Value: utils.GlobalBig(ctx, ValueFlag.Name), 105 EVMConfig: vm.Config{ 106 Tracer: logger, 107 Debug: ctx.GlobalBool(DebugFlag.Name), 108 DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name), 109 }, 110 } 111 112 if cpuProfilePath := ctx.GlobalString(CPUProfileFlag.Name); cpuProfilePath != "" { 113 f, err := os.Create(cpuProfilePath) 114 if err != nil { 115 fmt.Println("could not create CPU profile: ", err) 116 os.Exit(1) 117 } 118 if err := pprof.StartCPUProfile(f); err != nil { 119 fmt.Println("could not start CPU profile: ", err) 120 os.Exit(1) 121 } 122 defer pprof.StopCPUProfile() 123 } 124 125 tstart := time.Now() 126 if ctx.GlobalBool(CreateFlag.Name) { 127 input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...) 128 ret, _, err = runtime.Create(input, &runtimeConfig) 129 } else { 130 receiver := common.StringToAddress("receiver") 131 statedb.SetCode(receiver, code) 132 133 ret, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig) 134 } 135 execTime := time.Since(tstart) 136 137 if ctx.GlobalBool(DumpFlag.Name) { 138 statedb.Commit(true) 139 fmt.Println(string(statedb.Dump())) 140 } 141 142 if memProfilePath := ctx.GlobalString(MemProfileFlag.Name); memProfilePath != "" { 143 f, err := os.Create(memProfilePath) 144 if err != nil { 145 fmt.Println("could not create memory profile: ", err) 146 os.Exit(1) 147 } 148 if err := pprof.WriteHeapProfile(f); err != nil { 149 fmt.Println("could not write memory profile: ", err) 150 os.Exit(1) 151 } 152 f.Close() 153 } 154 155 if ctx.GlobalBool(DebugFlag.Name) { 156 fmt.Fprintln(os.Stderr, "#### TRACE ####") 157 vm.WriteTrace(os.Stderr, logger.StructLogs()) 158 fmt.Fprintln(os.Stderr, "#### LOGS ####") 159 vm.WriteLogs(os.Stderr, statedb.Logs()) 160 } 161 162 if ctx.GlobalBool(StatDumpFlag.Name) { 163 var mem goruntime.MemStats 164 goruntime.ReadMemStats(&mem) 165 fmt.Fprintf(os.Stderr, `evm execution time: %v 166 heap objects: %d 167 allocations: %d 168 total allocations: %d 169 GC calls: %d 170 171 `, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC) 172 } 173 174 fmt.Printf("0x%x", ret) 175 if err != nil { 176 fmt.Printf(" error: %v", err) 177 } 178 fmt.Println() 179 return nil 180 }