github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/cmd/wasm/runner.go (about) 1 package main 2 3 import ( 4 "github.com/PlatONnetwork/PlatON-Go/cmd/utils" 5 "github.com/PlatONnetwork/PlatON-Go/common" 6 "github.com/PlatONnetwork/PlatON-Go/core" 7 "github.com/PlatONnetwork/PlatON-Go/core/state" 8 "github.com/PlatONnetwork/PlatON-Go/core/vm" 9 "github.com/PlatONnetwork/PlatON-Go/ethdb" 10 "github.com/PlatONnetwork/PlatON-Go/life/runtime" 11 "github.com/PlatONnetwork/PlatON-Go/log" 12 "github.com/PlatONnetwork/PlatON-Go/params" 13 "github.com/PlatONnetwork/PlatON-Go/rlp" 14 "bytes" 15 "encoding/json" 16 "fmt" 17 "gopkg.in/urfave/cli.v1" 18 "io/ioutil" 19 "math/big" 20 "os" 21 "time" 22 23 covert "github.com/PlatONnetwork/PlatON-Go/life/utils" 24 goruntime "runtime" 25 ) 26 27 var runCommond = cli.Command{ 28 Action: runCmd, 29 Name: "run", 30 Usage: "run arbitrary wasm binary", 31 ArgsUsage: "<code>", 32 Description: "The run command runs arbitrary WASM code", 33 } 34 35 // readGenesis will read the given JSON format genesis file and 36 // return the initialized Genesis structure 37 func readGenesis(genesisPath string) *core.Genesis { 38 if len(genesisPath) == 0 { 39 utils.Fatalf("Must supply path to genesis JSON file") 40 } 41 file, err := os.Open(genesisPath) 42 if err != nil { 43 utils.Fatalf("Failed to read genesis file : %v", err) 44 } 45 defer file.Close() 46 47 genesis := new(core.Genesis) 48 if err := json.NewDecoder(file).Decode(genesis); err != nil { 49 utils.Fatalf("invalid genesis file : %v", err) 50 } 51 return genesis 52 } 53 54 func runCmd(ctx *cli.Context) error { 55 glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false))) 56 glogger.Verbosity(log.Lvl(ctx.GlobalInt(VerbosityFlag.Name))) 57 log.Root().SetHandler(glogger) 58 logconfig := &vm.LogConfig{ 59 DisableMemory: false, 60 DisableStack: false, 61 Debug: ctx.GlobalBool(DebugFlag.Name), 62 } 63 64 var ( 65 tracer vm.Tracer 66 debugLogger *vm.StructLogger 67 statedb *state.StateDB 68 chainConfig *params.ChainConfig 69 sender = common.BytesToAddress([]byte("sender")) 70 receiver = common.BytesToAddress([]byte("receiver")) 71 genesisConfig *core.Genesis 72 ) 73 if ctx.GlobalBool(MachineFlag.Name) { 74 tracer = NewJSONLogger(logconfig, os.Stdout) 75 } else if ctx.GlobalBool(DebugFlag.Name) { 76 debugLogger = vm.NewStructLogger(logconfig) 77 tracer = debugLogger 78 } else { 79 debugLogger = vm.NewStructLogger(logconfig) 80 } 81 if ctx.GlobalString(GenesisFlag.Name) != "" { 82 gen := readGenesis(ctx.GlobalString(GenesisFlag.Name)) 83 genesisConfig = gen 84 db := ethdb.NewMemDatabase() 85 genesis := gen.ToBlock(db) 86 statedb, _ = state.New(genesis.Root(), state.NewDatabase(db), genesis.Number(), genesis.Hash()) 87 chainConfig = gen.Config 88 } else { 89 statedb, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()), big.NewInt(0), common.Hash{}) 90 genesisConfig = new(core.Genesis) 91 } 92 if ctx.GlobalString(SenderFlag.Name) != "" { 93 sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name)) 94 } 95 statedb.CreateAccount(sender) 96 if ctx.GlobalString(ReceiverFlag.Name) != "" { 97 receiver = common.HexToAddress(ctx.GlobalString(ReceiverFlag.Name)) 98 } 99 100 var ( 101 code []byte 102 abi []byte 103 ret []byte 104 err error 105 ) 106 107 // The '--code' or '--codefile' flag overrides code in state 108 if ctx.GlobalString(CodeFileFlag.Name) != "" { 109 var hexcode []byte 110 var err error 111 if ctx.GlobalString(CodeFileFlag.Name) == "-" { 112 // try reading from stdin 113 if hexcode, err = ioutil.ReadAll(os.Stdin); err != nil { 114 utils.Fatalf("Could not load code from stdin : %v", err) 115 } 116 } else { 117 // codefile with hex assembly 118 if hexcode, err = ioutil.ReadFile(ctx.GlobalString(CodeFileFlag.Name)); err != nil { 119 utils.Fatalf("Could not load code from file: %v", err) 120 } 121 } 122 // Eliminate line breaks 123 code = common.Hex2Bytes(string(bytes.TrimRight(hexcode,"\n"))) 124 } else if ctx.GlobalString(CodeFlag.Name) != "" { 125 code = common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)) 126 } 127 128 // The '--abi' or '--abifile' flag overrides abi in state 129 if ctx.GlobalString(AbiFileFlag.Name) != "" { 130 var strabi []byte 131 var err error 132 if ctx.GlobalString(AbiFileFlag.Name) == "-" { 133 // try reading from stdin 134 if strabi, err = ioutil.ReadAll(os.Stdin); err != nil { 135 utils.Fatalf("Could not load abi from stdin : %v", err) 136 } 137 } else { 138 // codefile with hex assembly 139 if strabi, err = ioutil.ReadFile(ctx.GlobalString(AbiFileFlag.Name)); err != nil { 140 utils.Fatalf("Could not load abi from file: %v", err) 141 } 142 } 143 hexabi := common.Bytes2Hex(bytes.TrimRight(strabi,"\n")) 144 abi = common.Hex2Bytes(hexabi) 145 } else if ctx.GlobalString(AbiFlag.Name) != "" { 146 abi = []byte(ctx.GlobalString(AbiFlag.Name)) 147 } 148 149 initialGas := ctx.GlobalUint64(GasFlag.Name) 150 if genesisConfig.GasLimit != 0 { 151 initialGas = genesisConfig.GasLimit 152 } 153 runtimeConfig := runtime.Config{ 154 Origin: sender, 155 State: statedb, 156 GasLimit: initialGas, 157 GasPrice: utils.GlobalBig(ctx, GasPriceFlag.Name), 158 Value: utils.GlobalBig(ctx, ValueFlag.Name), 159 Time: new(big.Int).SetUint64(genesisConfig.Timestamp), 160 Coinbase: genesisConfig.Coinbase, 161 BlockNumber: new(big.Int).SetUint64(genesisConfig.Number), 162 EVMConfig: vm.Config{ 163 Tracer: tracer, 164 Debug: ctx.GlobalBool(DebugFlag.Name) || ctx.GlobalBool(MachineFlag.Name), 165 }, 166 } 167 168 if chainConfig != nil { 169 runtimeConfig.ChainConfig = chainConfig 170 } 171 172 txType := ctx.GlobalInt64(TxTypeFlag.Name) 173 174 tstart := time.Now() 175 var leftOverGas uint64 176 if ctx.GlobalBool(CreateFlag.Name) { 177 // Contract creation logic,Input is an external input, possibly a parameter。Need to be encoded in wasm to complete 178 rlpData := make([][]byte,0) 179 rlpData = append(rlpData, covert.Int64ToBytes(txType), abi, code) 180 181 buffer := new(bytes.Buffer) 182 err := rlp.Encode(buffer, rlpData) 183 if err != nil { 184 utils.Fatalf("rlp parse fail: %v", err) 185 } 186 ret, _, leftOverGas, err = runtime.Create(buffer.Bytes(), &runtimeConfig) 187 } else { 188 if len(code) > 0 { 189 statedb.SetCode(receiver, code) 190 } 191 if len(abi) > 0 { 192 statedb.SetAbi(receiver, abi) 193 } 194 // input : rlp.encoded format. 195 input := common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)) 196 ret, leftOverGas, err = runtime.Call(receiver, input, &runtimeConfig) 197 } 198 execTime := time.Since(tstart) 199 200 statedb.IntermediateRoot(true) 201 fmt.Println(string(statedb.Dump())) 202 203 if ctx.GlobalBool(StatDumpFlag.Name) { 204 var mem goruntime.MemStats 205 goruntime.ReadMemStats(&mem) 206 fmt.Fprintf(os.Stderr, `evm execution time: %v 207 heap objects: %d 208 allocations: %d 209 total allocations: %d 210 GC calls: %d 211 Gas used: %d 212 213 `, execTime, mem.HeapObjects, mem.Alloc, mem.TotalAlloc, mem.NumGC, initialGas-leftOverGas) 214 } 215 216 if tracer == nil { 217 fmt.Printf("0x%x\n", ret) 218 if err != nil { 219 fmt.Printf(" error: %v\n", err) 220 } 221 } 222 223 return nil 224 }