github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/cmd/evm/runner.go (about) 1 2 package main 3 4 import ( 5 "bytes" 6 "encoding/json" 7 "fmt" 8 "io/ioutil" 9 "math/big" 10 "os" 11 goruntime "runtime" 12 "runtime/pprof" 13 "time" 14 15 "github.com/quickchainproject/quickchain/cmd/evm/internal/compiler" 16 "github.com/quickchainproject/quickchain/cmd/utils" 17 "github.com/quickchainproject/quickchain/common" 18 "github.com/quickchainproject/quickchain/core" 19 "github.com/quickchainproject/quickchain/core/state" 20 "github.com/quickchainproject/quickchain/core/vm" 21 "github.com/quickchainproject/quickchain/core/vm/runtime" 22 "github.com/quickchainproject/quickchain/qctdb" 23 "github.com/quickchainproject/quickchain/log" 24 "github.com/quickchainproject/quickchain/params" 25 cli "gopkg.in/urfave/cli.v1" 26 ) 27 28 var runCommand = cli.Command{ 29 Action: runCmd, 30 Name: "run", 31 Usage: "run arbitrary evm binary", 32 ArgsUsage: "<code>", 33 Description: `The run command runs arbitrary EVM code.`, 34 } 35 36 // readGenesis will read the given JSON format genesis file and return 37 // the initialized Genesis structure 38 func readGenesis(genesisPath string) *core.Genesis { 39 // Make sure we have a valid genesis JSON 40 //genesisPath := ctx.Args().First() 41 if len(genesisPath) == 0 { 42 utils.Fatalf("Must supply path to genesis JSON file") 43 } 44 file, err := os.Open(genesisPath) 45 if err != nil { 46 utils.Fatalf("Failed to read genesis file: %v", err) 47 } 48 defer file.Close() 49 50 genesis := new(core.Genesis) 51 if err := json.NewDecoder(file).Decode(genesis); err != nil { 52 utils.Fatalf("invalid genesis file: %v", err) 53 } 54 return genesis 55 } 56 57 func runCmd(ctx *cli.Context) error { 58 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 59 glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) 60 log.Root().SetHandler(glogger) 61 logconfig := &vm.LogConfig{ 62 DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), 63 DisableStack: ctx.GlobalBool(DisableStackFlag.Name), 64 Debug: ctx.GlobalBool(DebugFlag.Name), 65 } 66 67 var ( 68 tracer vm.Tracer 69 debugLogger *vm.StructLogger 70 statedb *state.StateDB 71 chainConfig *params.ChainConfig 72 sender = common.BytesToAddress([]byte("sender")) 73 receiver = common.BytesToAddress([]byte("receiver")) 74 blockNumber uint64 75 ) 76 if ctx.GlobalBool(MachineFlag.Name) { 77 tracer = NewJSONLogger(logconfig, os.Stdout) 78 } else if ctx.GlobalBool(DebugFlag.Name) { 79 debugLogger = vm.NewStructLogger(logconfig) 80 tracer = debugLogger 81 } else { 82 debugLogger = vm.NewStructLogger(logconfig) 83 } 84 if ctx.GlobalString(GenesisFlag.Name) != "" { 85 gen := readGenesis(ctx.GlobalString(GenesisFlag.Name)) 86 db, _ := qctdb.NewMemDatabase() 87 genesis := gen.ToBlock(db) 88 statedb, _ = state.New(genesis.Root(), state.NewDatabase(db)) 89 chainConfig = gen.Config 90 blockNumber = gen.Number 91 } else { 92 db, _ := qctdb.NewMemDatabase() 93 statedb, _ = state.New(common.Hash{}, state.NewDatabase(db)) 94 } 95 if ctx.GlobalString(SenderFlag.Name) != "" { 96 sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name)) 97 } 98 statedb.CreateAccount(sender) 99 100 if ctx.GlobalString(ReceiverFlag.Name) != "" { 101 receiver = common.HexToAddress(ctx.GlobalString(ReceiverFlag.Name)) 102 } 103 104 var ( 105 code []byte 106 ret []byte 107 err error 108 ) 109 // The '--code' or '--codefile' flag overrides code in state 110 if ctx.GlobalString(CodeFileFlag.Name) != "" { 111 var hexcode []byte 112 var err error 113 // If - is specified, it means that code comes from stdin 114 if ctx.GlobalString(CodeFileFlag.Name) == "-" { 115 //Try reading from stdin 116 if hexcode, err = ioutil.ReadAll(os.Stdin); err != nil { 117 fmt.Printf("Could not load code from stdin: %v\n", err) 118 os.Exit(1) 119 } 120 } else { 121 // Codefile with hex assembly 122 if hexcode, err = ioutil.ReadFile(ctx.GlobalString(CodeFileFlag.Name)); err != nil { 123 fmt.Printf("Could not load code from file: %v\n", err) 124 os.Exit(1) 125 } 126 } 127 code = common.Hex2Bytes(string(bytes.TrimRight(hexcode, "\n"))) 128 129 } else if ctx.GlobalString(CodeFlag.Name) != "" { 130 code = common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)) 131 } else if fn := ctx.Args().First(); len(fn) > 0 { 132 // EASM-file to compile 133 src, err := ioutil.ReadFile(fn) 134 if err != nil { 135 return err 136 } 137 bin, err := compiler.Compile(fn, src, false) 138 if err != nil { 139 return err 140 } 141 code = common.Hex2Bytes(bin) 142 } 143 144 initialGas := ctx.GlobalUint64(GasFlag.Name) 145 runtimeConfig := runtime.Config{ 146 Origin: sender, 147 State: statedb, 148 GasLimit: initialGas, 149 GasPrice: utils.GlobalBig(ctx, PriceFlag.Name), 150 Value: utils.GlobalBig(ctx, ValueFlag.Name), 151 BlockNumber: new(big.Int).SetUint64(blockNumber), 152 EVMConfig: vm.Config{ 153 Tracer: tracer, 154 Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), 155 }, 156 } 157 158 if cpuProfilePath := ctx.GlobalString(CPUProfileFlag.Name); cpuProfilePath != "" { 159 f, err := os.Create(cpuProfilePath) 160 if err != nil { 161 fmt.Println("could not create CPU profile: ", err) 162 os.Exit(1) 163 } 164 if err := pprof.StartCPUProfile(f); err != nil { 165 fmt.Println("could not start CPU profile: ", err) 166 os.Exit(1) 167 } 168 defer pprof.StopCPUProfile() 169 } 170 171 if chainConfig != nil { 172 runtimeConfig.ChainConfig = chainConfig 173 } 174 tstart := time.Now() 175 var leftOverGas uint64 176 if ctx.GlobalBool(CreateFlag.Name) { 177 input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...) 178 ret, _, leftOverGas, err = runtime.Create(input, &runtimeConfig) 179 } else { 180 if len(code) > 0 { 181 statedb.SetCode(receiver, code) 182 } 183 ret, leftOverGas, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig) 184 } 185 execTime := time.Since(tstart) 186 187 if ctx.GlobalBool(DumpFlag.Name) { 188 statedb.IntermediateRoot(true) 189 fmt.Println(string(statedb.Dump())) 190 } 191 192 if memProfilePath := ctx.GlobalString(MemProfileFlag.Name); memProfilePath != "" { 193 f, err := os.Create(memProfilePath) 194 if err != nil { 195 fmt.Println("could not create memory profile: ", err) 196 os.Exit(1) 197 } 198 if err := pprof.WriteHeapProfile(f); err != nil { 199 fmt.Println("could not write memory profile: ", err) 200 os.Exit(1) 201 } 202 f.Close() 203 } 204 205 if ctx.GlobalBool(DebugFlag.Name) { 206 if debugLogger != nil { 207 fmt.Fprintln(os.Stderr, "#### TRACE ####") 208 vm.WriteTrace(os.Stderr, debugLogger.StructLogs()) 209 } 210 fmt.Fprintln(os.Stderr, "#### LOGS ####") 211 vm.WriteLogs(os.Stderr, statedb.Logs()) 212 } 213 214 if ctx.GlobalBool(StatDumpFlag.Name) { 215 var mem goruntime.MemStats 216 goruntime.ReadMemStats(&mem) 217 fmt.Fprintf(os.Stderr, `evm execution time: %v 218 heap objects: %d 219 allocations: %d 220 total allocations: %d 221 GC calls: %d 222 Gas used: %d 223 224 `, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas) 225 } 226 if tracer == nil { 227 fmt.Printf("0x%x\n", ret) 228 if err != nil { 229 fmt.Printf(" error: %v\n", err) 230 } 231 } 232 233 return nil 234 }