From 3fc7c978277051391f8ea7831559e9f4f83c3166 Mon Sep 17 00:00:00 2001 From: Jeffrey Wilcke Date: Tue, 6 Dec 2016 02:16:03 +0100 Subject: core, core/vm: implemented a generic environment (#3348) Environment is now a struct (not an interface). This reduces a lot of tech-debt throughout the codebase where a virtual machine environment had to be implemented in order to test or run it. The new environment is suitable to be used en the json tests, core consensus and light client. --- cmd/evm/main.go | 139 ++++++++++---------------------------------------------- 1 file changed, 25 insertions(+), 114 deletions(-) (limited to 'cmd/evm') diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 2c4329fa5..993dd7659 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -20,21 +20,18 @@ package main import ( "fmt" "io/ioutil" - "math/big" "os" - "runtime" + goruntime "runtime" "time" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/core/vm/runtime" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger/glog" - "github.com/ethereum/go-ethereum/params" "gopkg.in/urfave/cli.v1" ) @@ -129,13 +126,6 @@ func run(ctx *cli.Context) error { logger := vm.NewStructLogger(nil) - vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name)), vm.Config{ - Debug: ctx.GlobalBool(DebugFlag.Name), - ForceJit: ctx.GlobalBool(ForceJitFlag.Name), - EnableJit: !ctx.GlobalBool(DisableJitFlag.Name), - Tracer: logger, - }) - tstart := time.Now() var ( @@ -168,25 +158,30 @@ func run(ctx *cli.Context) error { if ctx.GlobalBool(CreateFlag.Name) { input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...) - ret, _, err = vmenv.Create( - sender, - input, - common.Big(ctx.GlobalString(GasFlag.Name)), - common.Big(ctx.GlobalString(PriceFlag.Name)), - common.Big(ctx.GlobalString(ValueFlag.Name)), - ) + ret, _, err = runtime.Create(input, &runtime.Config{ + Origin: sender.Address(), + State: statedb, + GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)), + GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)), + Value: common.Big(ctx.GlobalString(ValueFlag.Name)), + EVMConfig: vm.Config{ + Tracer: logger, + }, + }) } else { receiver := statedb.CreateAccount(common.StringToAddress("receiver")) - receiver.SetCode(crypto.Keccak256Hash(code), code) - ret, err = 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)), - ) + + ret, err = runtime.Call(receiver.Address(), common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtime.Config{ + Origin: sender.Address(), + State: statedb, + GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)), + GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)), + Value: common.Big(ctx.GlobalString(ValueFlag.Name)), + EVMConfig: vm.Config{ + Tracer: logger, + }, + }) } vmdone := time.Since(tstart) @@ -197,8 +192,8 @@ func run(ctx *cli.Context) error { vm.StdErrFormat(logger.StructLogs()) if ctx.GlobalBool(SysStatFlag.Name) { - var mem runtime.MemStats - runtime.ReadMemStats(&mem) + var mem goruntime.MemStats + goruntime.ReadMemStats(&mem) fmt.Printf("vm took %v\n", vmdone) fmt.Printf(`alloc: %d tot alloc: %d @@ -223,87 +218,3 @@ func main() { os.Exit(1) } } - -type VMEnv struct { - state *state.StateDB - block *types.Block - - transactor *common.Address - value *big.Int - - depth int - Gas *big.Int - time *big.Int - logs []vm.StructLog - - evm *vm.EVM -} - -func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg vm.Config) *VMEnv { - env := &VMEnv{ - state: state, - transactor: &transactor, - value: value, - time: big.NewInt(time.Now().Unix()), - } - - env.evm = vm.New(env, cfg) - return env -} - -// ruleSet implements vm.ChainConfig and will always default to the homestead rule set. -type ruleSet struct{} - -func (ruleSet) IsHomestead(*big.Int) bool { return true } -func (ruleSet) GasTable(*big.Int) params.GasTable { - return params.GasTableHomesteadGasRepriceFork -} - -func (self *VMEnv) ChainConfig() *params.ChainConfig { return params.TestChainConfig } -func (self *VMEnv) Vm() vm.Vm { return self.evm } -func (self *VMEnv) Db() vm.Database { return self.state } -func (self *VMEnv) SnapshotDatabase() int { return self.state.Snapshot() } -func (self *VMEnv) RevertToSnapshot(snap int) { self.state.RevertToSnapshot(snap) } -func (self *VMEnv) Origin() common.Address { return *self.transactor } -func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 } -func (self *VMEnv) Coinbase() common.Address { return *self.transactor } -func (self *VMEnv) Time() *big.Int { return self.time } -func (self *VMEnv) Difficulty() *big.Int { return common.Big1 } -func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) } -func (self *VMEnv) Value() *big.Int { return self.value } -func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) } -func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy } -func (self *VMEnv) Depth() int { return 0 } -func (self *VMEnv) SetDepth(i int) { self.depth = i } -func (self *VMEnv) GetHash(n uint64) common.Hash { - if self.block.Number().Cmp(big.NewInt(int64(n))) == 0 { - return self.block.Hash() - } - return common.Hash{} -} -func (self *VMEnv) AddLog(log *vm.Log) { - self.state.AddLog(log) -} -func (self *VMEnv) CanTransfer(from common.Address, balance *big.Int) bool { - return self.state.GetBalance(from).Cmp(balance) >= 0 -} -func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) { - core.Transfer(from, to, amount) -} - -func (self *VMEnv) Call(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - self.Gas = gas - return core.Call(self, caller, addr, data, gas, price, value) -} - -func (self *VMEnv) CallCode(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - return core.CallCode(self, caller, addr, data, gas, price, value) -} - -func (self *VMEnv) DelegateCall(caller vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) { - return core.DelegateCall(self, caller, addr, data, gas, price) -} - -func (self *VMEnv) Create(caller vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) { - return core.Create(self, caller, data, gas, price, value) -} -- cgit