github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/core/vm/runtime/runtime.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package runtime provides a basic execution model for executing EVM code.
    18  package runtime
    19  
    20  import (
    21  	"math/big"
    22  	"time"
    23  
    24  	"github.com/ethereumproject/go-ethereum/common"
    25  	"github.com/ethereumproject/go-ethereum/core/state"
    26  	"github.com/ethereumproject/go-ethereum/core/vm"
    27  	"github.com/ethereumproject/go-ethereum/crypto"
    28  	"github.com/ethereumproject/go-ethereum/ethdb"
    29  )
    30  
    31  // The default, always homestead, rule set for the vm env
    32  type ruleSet struct{}
    33  
    34  func (ruleSet) IsHomestead(*big.Int) bool { return true }
    35  func (ruleSet) GasTable(*big.Int) *vm.GasTable {
    36  	return &vm.GasTable{
    37  		ExtcodeSize:     big.NewInt(700),
    38  		ExtcodeCopy:     big.NewInt(700),
    39  		Balance:         big.NewInt(400),
    40  		SLoad:           big.NewInt(200),
    41  		Calls:           big.NewInt(700),
    42  		Suicide:         big.NewInt(5000),
    43  		ExpByte:         big.NewInt(10),
    44  		CreateBySuicide: big.NewInt(25000),
    45  	}
    46  }
    47  
    48  // Config is a basic type specifying certain configuration flags for running
    49  // the EVM.
    50  type Config struct {
    51  	RuleSet     vm.RuleSet
    52  	Difficulty  *big.Int
    53  	Origin      common.Address
    54  	Coinbase    common.Address
    55  	BlockNumber *big.Int
    56  	Time        *big.Int
    57  	GasLimit    *big.Int
    58  	GasPrice    *big.Int
    59  	Value       *big.Int
    60  	DisableJit  bool // "disable" so it's enabled by default
    61  	Debug       bool
    62  
    63  	State     *state.StateDB
    64  	GetHashFn func(n uint64) common.Hash
    65  }
    66  
    67  // sets defaults on the config
    68  func setDefaults(cfg *Config) {
    69  	if cfg.RuleSet == nil {
    70  		cfg.RuleSet = ruleSet{}
    71  	}
    72  
    73  	if cfg.Difficulty == nil {
    74  		cfg.Difficulty = new(big.Int)
    75  	}
    76  	if cfg.Time == nil {
    77  		cfg.Time = big.NewInt(time.Now().Unix())
    78  	}
    79  	if cfg.GasLimit == nil {
    80  		cfg.GasLimit = new(big.Int).Set(common.MaxBig)
    81  	}
    82  	if cfg.GasPrice == nil {
    83  		cfg.GasPrice = new(big.Int)
    84  	}
    85  	if cfg.Value == nil {
    86  		cfg.Value = new(big.Int)
    87  	}
    88  	if cfg.BlockNumber == nil {
    89  		cfg.BlockNumber = new(big.Int)
    90  	}
    91  	if cfg.GetHashFn == nil {
    92  		cfg.GetHashFn = func(n uint64) common.Hash {
    93  			return common.BytesToHash(crypto.Keccak256([]byte(new(big.Int).SetUint64(n).String())))
    94  		}
    95  	}
    96  }
    97  
    98  // Execute executes the code using the input as call data during the execution.
    99  // It returns the EVM's return value, the new state and an error if it failed.
   100  //
   101  // Executes sets up a in memory, temporarily, environment for the execution of
   102  // the given code. It enabled the JIT by default and make sure that it's restored
   103  // to it's original state afterwards.
   104  func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
   105  	if cfg == nil {
   106  		cfg = new(Config)
   107  	}
   108  	setDefaults(cfg)
   109  
   110  	if cfg.State == nil {
   111  		db, _ := ethdb.NewMemDatabase()
   112  		cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(db))
   113  	}
   114  	var (
   115  		vmenv    = NewEnv(cfg, cfg.State)
   116  		sender   = cfg.State.CreateAccount(cfg.Origin)
   117  		receiver = cfg.State.CreateAccount(common.StringToAddress("contract"))
   118  	)
   119  	// set the receiver's (the executing contract) code for execution.
   120  	receiver.SetCode(crypto.Keccak256Hash(code), code)
   121  
   122  	// Call the code with the given configuration.
   123  	ret, err := vmenv.Call(
   124  		sender,
   125  		receiver.Address(),
   126  		input,
   127  		cfg.GasLimit,
   128  		cfg.GasPrice,
   129  		cfg.Value,
   130  	)
   131  
   132  	return ret, cfg.State, err
   133  }
   134  
   135  // Call executes the code given by the contract's address. It will return the
   136  // EVM's return value or an error if it failed.
   137  //
   138  // Call, unlike Execute, requires a config and also requires the State field to
   139  // be set.
   140  func Call(address common.Address, input []byte, cfg *Config) ([]byte, error) {
   141  	setDefaults(cfg)
   142  
   143  	vmenv := NewEnv(cfg, cfg.State)
   144  
   145  	sender := cfg.State.GetOrNewStateObject(cfg.Origin)
   146  	// Call the code with the given configuration.
   147  	ret, err := vmenv.Call(
   148  		sender,
   149  		address,
   150  		input,
   151  		cfg.GasLimit,
   152  		cfg.GasPrice,
   153  		cfg.Value,
   154  	)
   155  
   156  	return ret, err
   157  }