gitlab.com/flarenetwork/coreth@v0.1.1/core/vm/runtime/runtime.go (about)

     1  // (c) 2019-2020, Ava Labs, Inc.
     2  //
     3  // This file is a derived work, based on the go-ethereum library whose original
     4  // notices appear below.
     5  //
     6  // It is distributed under a license compatible with the licensing terms of the
     7  // original code from which it is derived.
     8  //
     9  // Much love to the original authors for their work.
    10  // **********
    11  // Copyright 2015 The go-ethereum Authors
    12  // This file is part of the go-ethereum library.
    13  //
    14  // The go-ethereum library is free software: you can redistribute it and/or modify
    15  // it under the terms of the GNU Lesser General Public License as published by
    16  // the Free Software Foundation, either version 3 of the License, or
    17  // (at your option) any later version.
    18  //
    19  // The go-ethereum library is distributed in the hope that it will be useful,
    20  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    22  // GNU Lesser General Public License for more details.
    23  //
    24  // You should have received a copy of the GNU Lesser General Public License
    25  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    26  
    27  package runtime
    28  
    29  import (
    30  	"math"
    31  	"math/big"
    32  	"time"
    33  
    34  	"github.com/ethereum/go-ethereum/common"
    35  	"github.com/ethereum/go-ethereum/crypto"
    36  	"gitlab.com/flarenetwork/coreth/core/rawdb"
    37  	"gitlab.com/flarenetwork/coreth/core/state"
    38  	"gitlab.com/flarenetwork/coreth/core/vm"
    39  	"gitlab.com/flarenetwork/coreth/params"
    40  )
    41  
    42  // Config is a basic type specifying certain configuration flags for running
    43  // the EVM.
    44  type Config struct {
    45  	ChainConfig *params.ChainConfig
    46  	Difficulty  *big.Int
    47  	Origin      common.Address
    48  	Coinbase    common.Address
    49  	BlockNumber *big.Int
    50  	Time        *big.Int
    51  	GasLimit    uint64
    52  	GasPrice    *big.Int
    53  	Value       *big.Int
    54  	Debug       bool
    55  	EVMConfig   vm.Config
    56  	BaseFee     *big.Int
    57  
    58  	State     *state.StateDB
    59  	GetHashFn func(n uint64) common.Hash
    60  }
    61  
    62  // sets defaults on the config
    63  func setDefaults(cfg *Config) {
    64  	if cfg.ChainConfig == nil {
    65  		cfg.ChainConfig = &params.ChainConfig{
    66  			ChainID:                     big.NewInt(1),
    67  			HomesteadBlock:              new(big.Int),
    68  			DAOForkBlock:                new(big.Int),
    69  			DAOForkSupport:              false,
    70  			EIP150Block:                 new(big.Int),
    71  			EIP150Hash:                  common.Hash{},
    72  			EIP155Block:                 new(big.Int),
    73  			EIP158Block:                 new(big.Int),
    74  			ByzantiumBlock:              new(big.Int),
    75  			ConstantinopleBlock:         new(big.Int),
    76  			PetersburgBlock:             new(big.Int),
    77  			IstanbulBlock:               new(big.Int),
    78  			MuirGlacierBlock:            new(big.Int),
    79  			ApricotPhase1BlockTimestamp: new(big.Int),
    80  			ApricotPhase2BlockTimestamp: new(big.Int),
    81  			ApricotPhase3BlockTimestamp: new(big.Int),
    82  		}
    83  	}
    84  
    85  	if cfg.Difficulty == nil {
    86  		cfg.Difficulty = new(big.Int)
    87  	}
    88  	if cfg.Time == nil {
    89  		cfg.Time = big.NewInt(time.Now().Unix())
    90  	}
    91  	if cfg.GasLimit == 0 {
    92  		cfg.GasLimit = math.MaxUint64
    93  	}
    94  	if cfg.GasPrice == nil {
    95  		cfg.GasPrice = new(big.Int)
    96  	}
    97  	if cfg.Value == nil {
    98  		cfg.Value = new(big.Int)
    99  	}
   100  	if cfg.BlockNumber == nil {
   101  		cfg.BlockNumber = new(big.Int)
   102  	}
   103  	if cfg.GetHashFn == nil {
   104  		cfg.GetHashFn = func(n uint64) common.Hash {
   105  			return common.BytesToHash(crypto.Keccak256([]byte(new(big.Int).SetUint64(n).String())))
   106  		}
   107  	}
   108  	if cfg.BaseFee == nil {
   109  		cfg.BaseFee = big.NewInt(params.ApricotPhase3InitialBaseFee)
   110  	}
   111  }
   112  
   113  // Execute executes the code using the input as call data during the execution.
   114  // It returns the EVM's return value, the new state and an error if it failed.
   115  //
   116  // Execute sets up an in-memory, temporary, environment for the execution of
   117  // the given code. It makes sure that it's restored to its original state afterwards.
   118  func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
   119  	if cfg == nil {
   120  		cfg = new(Config)
   121  	}
   122  	setDefaults(cfg)
   123  
   124  	if cfg.State == nil {
   125  		cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
   126  	}
   127  	var (
   128  		address = common.BytesToAddress([]byte("contract"))
   129  		vmenv   = NewEnv(cfg)
   130  		sender  = vm.AccountRef(cfg.Origin)
   131  	)
   132  	if rules := cfg.ChainConfig.AvalancheRules(vmenv.Context.BlockNumber, vmenv.Context.Time); rules.IsApricotPhase2 {
   133  		cfg.State.PrepareAccessList(cfg.Origin, &address, vm.ActivePrecompiles(rules), nil)
   134  	}
   135  	cfg.State.CreateAccount(address)
   136  	// set the receiver's (the executing contract) code for execution.
   137  	cfg.State.SetCode(address, code)
   138  	// Call the code with the given configuration.
   139  	ret, _, err := vmenv.Call(
   140  		sender,
   141  		common.BytesToAddress([]byte("contract")),
   142  		input,
   143  		cfg.GasLimit,
   144  		cfg.Value,
   145  	)
   146  
   147  	return ret, cfg.State, err
   148  }
   149  
   150  // Create executes the code using the EVM create method
   151  func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
   152  	if cfg == nil {
   153  		cfg = new(Config)
   154  	}
   155  	setDefaults(cfg)
   156  
   157  	if cfg.State == nil {
   158  		cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
   159  	}
   160  	var (
   161  		vmenv  = NewEnv(cfg)
   162  		sender = vm.AccountRef(cfg.Origin)
   163  	)
   164  	if rules := cfg.ChainConfig.AvalancheRules(vmenv.Context.BlockNumber, vmenv.Context.Time); rules.IsApricotPhase2 {
   165  		cfg.State.PrepareAccessList(cfg.Origin, nil, vm.ActivePrecompiles(rules), nil)
   166  	}
   167  	// Call the code with the given configuration.
   168  	code, address, leftOverGas, err := vmenv.Create(
   169  		sender,
   170  		input,
   171  		cfg.GasLimit,
   172  		cfg.Value,
   173  	)
   174  	return code, address, leftOverGas, err
   175  }
   176  
   177  // Call executes the code given by the contract's address. It will return the
   178  // EVM's return value or an error if it failed.
   179  //
   180  // Call, unlike Execute, requires a config and also requires the State field to
   181  // be set.
   182  func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, error) {
   183  	setDefaults(cfg)
   184  
   185  	vmenv := NewEnv(cfg)
   186  
   187  	sender := cfg.State.GetOrNewStateObject(cfg.Origin)
   188  	statedb := cfg.State
   189  
   190  	if rules := cfg.ChainConfig.AvalancheRules(vmenv.Context.BlockNumber, vmenv.Context.Time); rules.IsApricotPhase2 {
   191  		statedb.PrepareAccessList(cfg.Origin, &address, vm.ActivePrecompiles(rules), nil)
   192  	}
   193  	// Call the code with the given configuration.
   194  	ret, leftOverGas, err := vmenv.Call(
   195  		sender,
   196  		address,
   197  		input,
   198  		cfg.GasLimit,
   199  		cfg.Value,
   200  	)
   201  	return ret, leftOverGas, err
   202  }