github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/cmd/evm/runner.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2017 Go Ethereum作者 10 //此文件是Go以太坊的一部分。 11 // 12 //Go以太坊是免费软件:您可以重新发布和/或修改它 13 //根据GNU通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊的分布希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 // 21 // 22 //你应该已经收到一份GNU通用公共许可证的副本 23 //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package main 26 27 import ( 28 "bytes" 29 "encoding/json" 30 "fmt" 31 "io/ioutil" 32 "math/big" 33 "os" 34 goruntime "runtime" 35 "runtime/pprof" 36 "time" 37 38 "github.com/ethereum/go-ethereum/cmd/evm/internal/compiler" 39 "github.com/ethereum/go-ethereum/cmd/utils" 40 "github.com/ethereum/go-ethereum/common" 41 "github.com/ethereum/go-ethereum/core" 42 "github.com/ethereum/go-ethereum/core/state" 43 "github.com/ethereum/go-ethereum/core/vm" 44 "github.com/ethereum/go-ethereum/core/vm/runtime" 45 "github.com/ethereum/go-ethereum/ethdb" 46 "github.com/ethereum/go-ethereum/log" 47 "github.com/ethereum/go-ethereum/params" 48 cli "gopkg.in/urfave/cli.v1" 49 ) 50 51 var runCommand = cli.Command{ 52 Action: runCmd, 53 Name: "run", 54 Usage: "run arbitrary evm binary", 55 ArgsUsage: "<code>", 56 Description: `The run command runs arbitrary EVM code.`, 57 } 58 59 //read genesis将读取给定的JSON格式genesis文件并返回 60 //初始化的Genesis结构 61 func readGenesis(genesisPath string) *core.Genesis { 62 //确保我们有一个有效的Genesis JSON 63 //genesPath:=ctx.args().first()) 64 if len(genesisPath) == 0 { 65 utils.Fatalf("Must supply path to genesis JSON file") 66 } 67 file, err := os.Open(genesisPath) 68 if err != nil { 69 utils.Fatalf("Failed to read genesis file: %v", err) 70 } 71 defer file.Close() 72 73 genesis := new(core.Genesis) 74 if err := json.NewDecoder(file).Decode(genesis); err != nil { 75 utils.Fatalf("invalid genesis file: %v", err) 76 } 77 return genesis 78 } 79 80 func runCmd(ctx *cli.Context) error { 81 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 82 glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) 83 log.Root().SetHandler(glogger) 84 logconfig := &vm.LogConfig{ 85 DisableMemory: ctx.GlobalBool(DisableMemoryFlag.Name), 86 DisableStack: ctx.GlobalBool(DisableStackFlag.Name), 87 Debug: ctx.GlobalBool(DebugFlag.Name), 88 } 89 90 var ( 91 tracer vm.Tracer 92 debugLogger *vm.StructLogger 93 statedb *state.StateDB 94 chainConfig *params.ChainConfig 95 sender = common.BytesToAddress([]byte("sender")) 96 receiver = common.BytesToAddress([]byte("receiver")) 97 blockNumber uint64 98 ) 99 if ctx.GlobalBool(MachineFlag.Name) { 100 tracer = NewJSONLogger(logconfig, os.Stdout) 101 } else if ctx.GlobalBool(DebugFlag.Name) { 102 debugLogger = vm.NewStructLogger(logconfig) 103 tracer = debugLogger 104 } else { 105 debugLogger = vm.NewStructLogger(logconfig) 106 } 107 if ctx.GlobalString(GenesisFlag.Name) != "" { 108 gen := readGenesis(ctx.GlobalString(GenesisFlag.Name)) 109 db := ethdb.NewMemDatabase() 110 genesis := gen.ToBlock(db) 111 statedb, _ = state.New(genesis.Root(), state.NewDatabase(db)) 112 chainConfig = gen.Config 113 blockNumber = gen.Number 114 } else { 115 statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase())) 116 } 117 if ctx.GlobalString(SenderFlag.Name) != "" { 118 sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name)) 119 } 120 statedb.CreateAccount(sender) 121 122 if ctx.GlobalString(ReceiverFlag.Name) != "" { 123 receiver = common.HexToAddress(ctx.GlobalString(ReceiverFlag.Name)) 124 } 125 126 var ( 127 code []byte 128 ret []byte 129 err error 130 ) 131 //“--code”或“--codefile”标志重写处于状态的代码 132 if ctx.GlobalString(CodeFileFlag.Name) != "" { 133 var hexcode []byte 134 var err error 135 //如果指定了-则表示代码来自stdin 136 if ctx.GlobalString(CodeFileFlag.Name) == "-" { 137 //尝试从stdin读取 138 if hexcode, err = ioutil.ReadAll(os.Stdin); err != nil { 139 fmt.Printf("Could not load code from stdin: %v\n", err) 140 os.Exit(1) 141 } 142 } else { 143 //带十六进制程序集的代码文件 144 if hexcode, err = ioutil.ReadFile(ctx.GlobalString(CodeFileFlag.Name)); err != nil { 145 fmt.Printf("Could not load code from file: %v\n", err) 146 os.Exit(1) 147 } 148 } 149 code = common.Hex2Bytes(string(bytes.TrimRight(hexcode, "\n"))) 150 151 } else if ctx.GlobalString(CodeFlag.Name) != "" { 152 code = common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)) 153 } else if fn := ctx.Args().First(); len(fn) > 0 { 154 //要编译的EASM文件 155 src, err := ioutil.ReadFile(fn) 156 if err != nil { 157 return err 158 } 159 bin, err := compiler.Compile(fn, src, false) 160 if err != nil { 161 return err 162 } 163 code = common.Hex2Bytes(bin) 164 } 165 166 initialGas := ctx.GlobalUint64(GasFlag.Name) 167 runtimeConfig := runtime.Config{ 168 Origin: sender, 169 State: statedb, 170 GasLimit: initialGas, 171 GasPrice: utils.GlobalBig(ctx, PriceFlag.Name), 172 Value: utils.GlobalBig(ctx, ValueFlag.Name), 173 BlockNumber: new(big.Int).SetUint64(blockNumber), 174 EVMConfig: vm.Config{ 175 Tracer: tracer, 176 Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), 177 }, 178 } 179 180 if cpuProfilePath := ctx.GlobalString(CPUProfileFlag.Name); cpuProfilePath != "" { 181 f, err := os.Create(cpuProfilePath) 182 if err != nil { 183 fmt.Println("could not create CPU profile: ", err) 184 os.Exit(1) 185 } 186 if err := pprof.StartCPUProfile(f); err != nil { 187 fmt.Println("could not start CPU profile: ", err) 188 os.Exit(1) 189 } 190 defer pprof.StopCPUProfile() 191 } 192 193 if chainConfig != nil { 194 runtimeConfig.ChainConfig = chainConfig 195 } 196 tstart := time.Now() 197 var leftOverGas uint64 198 if ctx.GlobalBool(CreateFlag.Name) { 199 input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...) 200 ret, _, leftOverGas, err = runtime.Create(input, &runtimeConfig) 201 } else { 202 if len(code) > 0 { 203 statedb.SetCode(receiver, code) 204 } 205 ret, leftOverGas, err = runtime.Call(receiver, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtimeConfig) 206 } 207 execTime := time.Since(tstart) 208 209 if ctx.GlobalBool(DumpFlag.Name) { 210 statedb.IntermediateRoot(true) 211 fmt.Println(string(statedb.Dump())) 212 } 213 214 if memProfilePath := ctx.GlobalString(MemProfileFlag.Name); memProfilePath != "" { 215 f, err := os.Create(memProfilePath) 216 if err != nil { 217 fmt.Println("could not create memory profile: ", err) 218 os.Exit(1) 219 } 220 if err := pprof.WriteHeapProfile(f); err != nil { 221 fmt.Println("could not write memory profile: ", err) 222 os.Exit(1) 223 } 224 f.Close() 225 } 226 227 if ctx.GlobalBool(DebugFlag.Name) { 228 if debugLogger != nil { 229 fmt.Fprintln(os.Stderr, "#### TRACE ####") 230 vm.WriteTrace(os.Stderr, debugLogger.StructLogs()) 231 } 232 fmt.Fprintln(os.Stderr, "#### LOGS ####") 233 vm.WriteLogs(os.Stderr, statedb.Logs()) 234 } 235 236 if ctx.GlobalBool(StatDumpFlag.Name) { 237 var mem goruntime.MemStats 238 goruntime.ReadMemStats(&mem) 239 fmt.Fprintf(os.Stderr, `evm execution time: %v 240 heap objects: %d 241 allocations: %d 242 total allocations: %d 243 GC calls: %d 244 Gas used: %d 245 246 `, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas) 247 } 248 if tracer == nil { 249 fmt.Printf("0x%x\n", ret) 250 if err != nil { 251 fmt.Printf(" error: %v\n", err) 252 } 253 } 254 255 return nil 256 }