func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, err error) { if err = self.preCheck(); err != nil { return } msg := self.msg sender, _ := self.From() // err checked in preCheck // Pay intrinsic gas if err = self.UseGas(IntrinsicGas(self.data)); err != nil { return nil, nil, InvalidTxError(err) } vmenv := self.env var ref vm.ContextRef if MessageCreatesContract(msg) { ret, err, ref = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value) if err == nil { dataGas := big.NewInt(int64(len(ret))) dataGas.Mul(dataGas, params.CreateDataGas) if err := self.UseGas(dataGas); err == nil { ref.SetCode(ret) } else { ret = nil // does not affect consensus but useful for StateTests validations glog.V(logger.Core).Infoln("Insufficient gas for creating code. Require", dataGas, "and have", self.gas) } } glog.V(logger.Core).Infoln("VM create err:", err) } else { // Increment the nonce for the next transaction self.state.SetNonce(sender.Address(), sender.Nonce()+1) ret, err = vmenv.Call(sender, self.To().Address(), self.data, self.gas, self.gasPrice, self.value) glog.V(logger.Core).Infoln("VM call err:", err) } if err != nil && IsValueTransferErr(err) { return nil, nil, InvalidTxError(err) } // We aren't interested in errors here. Errors returned by the VM are non-consensus errors and therefor shouldn't bubble up if err != nil { err = nil } if vm.Debug { vm.StdErrFormat(vmenv.StructLogs()) } self.refundGas() self.state.AddBalance(self.env.Coinbase(), new(big.Int).Mul(self.gasUsed(), self.gasPrice)) return ret, self.gasUsed(), err }
func run(ctx *cli.Context) { vm.Debug = ctx.GlobalBool(DebugFlag.Name) vm.ForceJit = ctx.GlobalBool(ForceJitFlag.Name) vm.EnableJit = !ctx.GlobalBool(DisableJitFlag.Name) glog.SetToStderr(true) db, _ := ethdb.NewMemDatabase() statedb := state.New(common.Hash{}, db) sender := statedb.CreateAccount(common.StringToAddress("sender")) receiver := statedb.CreateAccount(common.StringToAddress("receiver")) receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))) vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name))) tstart := time.Now() ret, e := vmenv.Call( sender, receiver.Address(), common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), common.Big(ctx.GlobalString(GasFlag.Name)), common.Big(ctx.GlobalString(PriceFlag.Name)), common.Big(ctx.GlobalString(ValueFlag.Name)), ) vmdone := time.Since(tstart) if ctx.GlobalBool(DumpFlag.Name) { fmt.Println(string(statedb.Dump())) } vm.StdErrFormat(vmenv.StructLogs()) if ctx.GlobalBool(SysStatFlag.Name) { var mem runtime.MemStats runtime.ReadMemStats(&mem) fmt.Printf("vm took %v\n", vmdone) fmt.Printf(`alloc: %d tot alloc: %d no. malloc: %d heap alloc: %d heap objs: %d num gc: %d `, mem.Alloc, mem.TotalAlloc, mem.Mallocs, mem.HeapAlloc, mem.HeapObjects, mem.NumGC) } fmt.Printf("OUT: 0x%x", ret) if e != nil { fmt.Printf(" error: %v", e) } fmt.Println() }