aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/evm/runtime/runtime.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm/evm/runtime/runtime.go')
-rw-r--r--core/vm/evm/runtime/runtime.go170
1 files changed, 170 insertions, 0 deletions
diff --git a/core/vm/evm/runtime/runtime.go b/core/vm/evm/runtime/runtime.go
new file mode 100644
index 000000000..93e6322f4
--- /dev/null
+++ b/core/vm/evm/runtime/runtime.go
@@ -0,0 +1,170 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package runtime
+
+import (
+ "math"
+ "math/big"
+ "time"
+
+ "github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/core/state"
+ vm "github.com/dexon-foundation/dexon/core/vm/evm"
+ "github.com/dexon-foundation/dexon/crypto"
+ "github.com/dexon-foundation/dexon/ethdb"
+ "github.com/dexon-foundation/dexon/params"
+)
+
+// Config is a basic type specifying certain configuration flags for running
+// the EVM.
+type Config struct {
+ ChainConfig *params.ChainConfig
+ Difficulty *big.Int
+ Origin common.Address
+ Coinbase common.Address
+ BlockNumber *big.Int
+ Time *big.Int
+ GasLimit uint64
+ GasPrice *big.Int
+ Value *big.Int
+ Debug bool
+ EVMConfig vm.Config
+
+ State *state.StateDB
+ GetHashFn func(n uint64) common.Hash
+}
+
+// sets defaults on the config
+func setDefaults(cfg *Config) {
+ if cfg.ChainConfig == nil {
+ cfg.ChainConfig = &params.ChainConfig{
+ ChainID: big.NewInt(1),
+ HomesteadBlock: new(big.Int),
+ DAOForkBlock: new(big.Int),
+ DAOForkSupport: false,
+ EIP150Block: new(big.Int),
+ EIP155Block: new(big.Int),
+ EIP158Block: new(big.Int),
+ }
+ }
+
+ if cfg.Difficulty == nil {
+ cfg.Difficulty = new(big.Int)
+ }
+ if cfg.Time == nil {
+ cfg.Time = big.NewInt(time.Now().Unix())
+ }
+ if cfg.GasLimit == 0 {
+ cfg.GasLimit = math.MaxUint64
+ }
+ if cfg.GasPrice == nil {
+ cfg.GasPrice = new(big.Int)
+ }
+ if cfg.Value == nil {
+ cfg.Value = new(big.Int)
+ }
+ if cfg.BlockNumber == nil {
+ cfg.BlockNumber = new(big.Int)
+ }
+ if cfg.GetHashFn == nil {
+ cfg.GetHashFn = func(n uint64) common.Hash {
+ return common.BytesToHash(crypto.Keccak256([]byte(new(big.Int).SetUint64(n).String())))
+ }
+ }
+}
+
+// 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 makes 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)
+
+ if cfg.State == nil {
+ cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ }
+ var (
+ address = common.BytesToAddress([]byte("contract"))
+ vmenv = NewEnv(cfg)
+ sender = vm.AccountRef(cfg.Origin)
+ )
+ cfg.State.CreateAccount(address)
+ // set the receiver's (the executing contract) code for execution.
+ cfg.State.SetCode(address, code)
+ // Call the code with the given configuration.
+ ret, _, err := vmenv.Call(
+ sender,
+ common.BytesToAddress([]byte("contract")),
+ input,
+ cfg.GasLimit,
+ cfg.Value,
+ )
+
+ return ret, cfg.State, err
+}
+
+// Create executes the code using the EVM create method
+func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
+ if cfg == nil {
+ cfg = new(Config)
+ }
+ setDefaults(cfg)
+
+ if cfg.State == nil {
+ cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(ethdb.NewMemDatabase()))
+ }
+ var (
+ vmenv = NewEnv(cfg)
+ sender = vm.AccountRef(cfg.Origin)
+ )
+
+ // Call the code with the given configuration.
+ code, address, leftOverGas, err := vmenv.Create(
+ sender,
+ input,
+ cfg.GasLimit,
+ cfg.Value,
+ )
+ return code, address, leftOverGas, err
+}
+
+// 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, uint64, error) {
+ setDefaults(cfg)
+
+ vmenv := NewEnv(cfg)
+
+ sender := cfg.State.GetOrNewStateObject(cfg.Origin)
+ // Call the code with the given configuration.
+ ret, leftOverGas, err := vmenv.Call(
+ sender,
+ address,
+ input,
+ cfg.GasLimit,
+ cfg.Value,
+ )
+
+ return ret, leftOverGas, err
+}