Exemple #1
0
// Call executes the code given by the contract's address. It will return the
// EVM's return value or an error if it failed.
//
// Call, unlike Execute, requires a config and also requires the State field to
// be set.
func Call(address common.Address, input []byte, cfg *Config) ([]byte, error) {
	setDefaults(cfg)

	// defer the call to setting back the original values
	defer func(debug, forceJit, enableJit bool) {
		vm.Debug = debug
		vm.ForceJit = forceJit
		vm.EnableJit = enableJit
	}(vm.Debug, vm.ForceJit, vm.EnableJit)

	vm.ForceJit = !cfg.DisableJit
	vm.EnableJit = !cfg.DisableJit
	vm.Debug = cfg.Debug

	vmenv := NewEnv(cfg, cfg.State)

	sender := cfg.State.GetOrNewStateObject(cfg.Origin)
	// Call the code with the given configuration.
	ret, err := vmenv.Call(
		sender,
		address,
		input,
		cfg.GasLimit,
		cfg.GasPrice,
		cfg.Value,
	)

	if cfg.Debug {
		vm.StdErrFormat(vmenv.StructLogs())
	}
	return ret, err
}
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 (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err error) {
	if err = self.preCheck(); err != nil {
		return
	}
	msg := self.msg
	sender, _ := self.from() // err checked in preCheck

	homestead := params.IsHomestead(self.env.BlockNumber())
	contractCreation := MessageCreatesContract(msg)
	// Pay intrinsic gas
	if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil {
		return nil, nil, InvalidTxError(err)
	}

	vmenv := self.env
	//var addr common.Address
	if contractCreation {
		ret, _, err = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
		if homestead && err == vm.CodeStoreOutOfGasError {
			self.gas = Big0
		}

		if err != nil {
			ret = nil
			glog.V(logger.Core).Infoln("VM create err:", err)
		}
	} else {
		// Increment the nonce for the next transaction
		self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1)
		ret, err = vmenv.Call(sender, self.to().Address(), self.data, self.gas, self.gasPrice, self.value)
		if err != nil {
			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
}
Exemple #4
0
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)
	glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))

	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()
}
Exemple #5
0
// Execute executes the code using the input as call data during the execution.
// It returns the EVM's return value, the new state and an error if it failed.
//
// Executes sets up a in memory, temporarily, environment for the execution of
// the given code. It enabled the JIT by default and make sure that it's restored
// to it's original state afterwards.
func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
	if cfg == nil {
		cfg = new(Config)
	}
	setDefaults(cfg)

	// defer the call to setting back the original values
	defer func(debug, forceJit, enableJit bool) {
		vm.Debug = debug
		vm.ForceJit = forceJit
		vm.EnableJit = enableJit
	}(vm.Debug, vm.ForceJit, vm.EnableJit)

	vm.ForceJit = !cfg.DisableJit
	vm.EnableJit = !cfg.DisableJit
	vm.Debug = cfg.Debug

	if cfg.State == nil {
		db, _ := ethdb.NewMemDatabase()
		cfg.State, _ = state.New(common.Hash{}, db)
	}
	var (
		vmenv    = NewEnv(cfg, cfg.State)
		sender   = cfg.State.CreateAccount(cfg.Origin)
		receiver = cfg.State.CreateAccount(common.StringToAddress("contract"))
	)
	// set the receiver's (the executing contract) code for execution.
	receiver.SetCode(code)

	// Call the code with the given configuration.
	ret, err := vmenv.Call(
		sender,
		receiver.Address(),
		input,
		cfg.GasLimit,
		cfg.GasPrice,
		cfg.Value,
	)

	if cfg.Debug {
		vm.StdErrFormat(vmenv.StructLogs())
	}
	return ret, cfg.State, err
}
Exemple #6
0
func main() {
	flag.Parse()

	logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.LogLevel(*loglevel)))

	vm.Debug = 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(*code))

	vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(*value))

	tstart := time.Now()

	ret, e := vmenv.Call(sender, receiver.Address(), common.Hex2Bytes(*data), common.Big(*gas), common.Big(*price), common.Big(*value))

	logger.Flush()
	if e != nil {
		perr(e)
	}

	if *dump {
		fmt.Println(string(statedb.Dump()))
	}

	vm.StdErrFormat(vmenv.StructLogs())

	var mem runtime.MemStats
	runtime.ReadMemStats(&mem)
	fmt.Printf("vm took %v\n", time.Since(tstart))
	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("%x\n", ret)
}