github.com/ethereum/go-ethereum@v1.16.1/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
    18  
    19  import (
    20  	"math"
    21  	"math/big"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/core/state"
    25  	"github.com/ethereum/go-ethereum/core/types"
    26  	"github.com/ethereum/go-ethereum/core/vm"
    27  	"github.com/ethereum/go-ethereum/crypto"
    28  	"github.com/ethereum/go-ethereum/params"
    29  	"github.com/holiman/uint256"
    30  )
    31  
    32  // Config is a basic type specifying certain configuration flags for running
    33  // the EVM.
    34  type Config struct {
    35  	ChainConfig *params.ChainConfig
    36  	Difficulty  *big.Int
    37  	Origin      common.Address
    38  	Coinbase    common.Address
    39  	BlockNumber *big.Int
    40  	Time        uint64
    41  	GasLimit    uint64
    42  	GasPrice    *big.Int
    43  	Value       *big.Int
    44  	Debug       bool
    45  	EVMConfig   vm.Config
    46  	BaseFee     *big.Int
    47  	BlobBaseFee *big.Int
    48  	BlobHashes  []common.Hash
    49  	BlobFeeCap  *big.Int
    50  	Random      *common.Hash
    51  
    52  	State     *state.StateDB
    53  	GetHashFn func(n uint64) common.Hash
    54  }
    55  
    56  // sets defaults on the config
    57  func setDefaults(cfg *Config) {
    58  	if cfg.ChainConfig == nil {
    59  		var (
    60  			shanghaiTime = uint64(0)
    61  			cancunTime   = uint64(0)
    62  		)
    63  		cfg.ChainConfig = &params.ChainConfig{
    64  			ChainID:                 big.NewInt(1),
    65  			HomesteadBlock:          new(big.Int),
    66  			DAOForkBlock:            new(big.Int),
    67  			DAOForkSupport:          false,
    68  			EIP150Block:             new(big.Int),
    69  			EIP155Block:             new(big.Int),
    70  			EIP158Block:             new(big.Int),
    71  			ByzantiumBlock:          new(big.Int),
    72  			ConstantinopleBlock:     new(big.Int),
    73  			PetersburgBlock:         new(big.Int),
    74  			IstanbulBlock:           new(big.Int),
    75  			MuirGlacierBlock:        new(big.Int),
    76  			BerlinBlock:             new(big.Int),
    77  			LondonBlock:             new(big.Int),
    78  			ArrowGlacierBlock:       nil,
    79  			GrayGlacierBlock:        nil,
    80  			TerminalTotalDifficulty: big.NewInt(0),
    81  			MergeNetsplitBlock:      nil,
    82  			ShanghaiTime:            &shanghaiTime,
    83  			CancunTime:              &cancunTime}
    84  	}
    85  	if cfg.Difficulty == nil {
    86  		cfg.Difficulty = new(big.Int)
    87  	}
    88  	if cfg.GasLimit == 0 {
    89  		cfg.GasLimit = math.MaxUint64
    90  	}
    91  	if cfg.GasPrice == nil {
    92  		cfg.GasPrice = new(big.Int)
    93  	}
    94  	if cfg.Value == nil {
    95  		cfg.Value = new(big.Int)
    96  	}
    97  	if cfg.BlockNumber == nil {
    98  		cfg.BlockNumber = new(big.Int)
    99  	}
   100  	if cfg.GetHashFn == nil {
   101  		cfg.GetHashFn = func(n uint64) common.Hash {
   102  			return common.BytesToHash(crypto.Keccak256([]byte(new(big.Int).SetUint64(n).String())))
   103  		}
   104  	}
   105  	if cfg.BaseFee == nil {
   106  		cfg.BaseFee = big.NewInt(params.InitialBaseFee)
   107  	}
   108  	if cfg.BlobBaseFee == nil {
   109  		cfg.BlobBaseFee = big.NewInt(params.BlobTxMinBlobGasprice)
   110  	}
   111  	cfg.Random = &(common.Hash{})
   112  }
   113  
   114  // Execute executes the code using the input as call data during the execution.
   115  // It returns the EVM's return value, the new state and an error if it failed.
   116  //
   117  // Execute sets up an in-memory, temporary, environment for the execution of
   118  // the given code. It makes sure that it's restored to its original state afterwards.
   119  func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
   120  	if cfg == nil {
   121  		cfg = new(Config)
   122  	}
   123  	setDefaults(cfg)
   124  
   125  	if cfg.State == nil {
   126  		cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
   127  	}
   128  	var (
   129  		address = common.BytesToAddress([]byte("contract"))
   130  		vmenv   = NewEnv(cfg)
   131  		rules   = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
   132  	)
   133  	if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxStart != nil {
   134  		cfg.EVMConfig.Tracer.OnTxStart(vmenv.GetVMContext(), types.NewTx(&types.LegacyTx{To: &address, Data: input, Value: cfg.Value, Gas: cfg.GasLimit}), cfg.Origin)
   135  	}
   136  	// Execute the preparatory steps for state transition which includes:
   137  	// - prepare accessList(post-berlin)
   138  	// - reset transient storage(eip 1153)
   139  	cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil)
   140  	cfg.State.CreateAccount(address)
   141  	// set the receiver's (the executing contract) code for execution.
   142  	cfg.State.SetCode(address, code)
   143  	// Call the code with the given configuration.
   144  	ret, leftOverGas, err := vmenv.Call(
   145  		cfg.Origin,
   146  		common.BytesToAddress([]byte("contract")),
   147  		input,
   148  		cfg.GasLimit,
   149  		uint256.MustFromBig(cfg.Value),
   150  	)
   151  	if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil {
   152  		cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err)
   153  	}
   154  	return ret, cfg.State, err
   155  }
   156  
   157  // Create executes the code using the EVM create method
   158  func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
   159  	if cfg == nil {
   160  		cfg = new(Config)
   161  	}
   162  	setDefaults(cfg)
   163  
   164  	if cfg.State == nil {
   165  		cfg.State, _ = state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
   166  	}
   167  	var (
   168  		vmenv = NewEnv(cfg)
   169  		rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
   170  	)
   171  	if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxStart != nil {
   172  		cfg.EVMConfig.Tracer.OnTxStart(vmenv.GetVMContext(), types.NewTx(&types.LegacyTx{Data: input, Value: cfg.Value, Gas: cfg.GasLimit}), cfg.Origin)
   173  	}
   174  	// Execute the preparatory steps for state transition which includes:
   175  	// - prepare accessList(post-berlin)
   176  	// - reset transient storage(eip 1153)
   177  	cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, nil, vm.ActivePrecompiles(rules), nil)
   178  	// Call the code with the given configuration.
   179  	code, address, leftOverGas, err := vmenv.Create(
   180  		cfg.Origin,
   181  		input,
   182  		cfg.GasLimit,
   183  		uint256.MustFromBig(cfg.Value),
   184  	)
   185  	if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil {
   186  		cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err)
   187  	}
   188  	return code, address, leftOverGas, err
   189  }
   190  
   191  // Call executes the code given by the contract's address. It will return the
   192  // EVM's return value or an error if it failed.
   193  //
   194  // Call, unlike Execute, requires a config and also requires the State field to
   195  // be set.
   196  func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, error) {
   197  	setDefaults(cfg)
   198  
   199  	var (
   200  		vmenv   = NewEnv(cfg)
   201  		statedb = cfg.State
   202  		rules   = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time)
   203  	)
   204  	if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxStart != nil {
   205  		cfg.EVMConfig.Tracer.OnTxStart(vmenv.GetVMContext(), types.NewTx(&types.LegacyTx{To: &address, Data: input, Value: cfg.Value, Gas: cfg.GasLimit}), cfg.Origin)
   206  	}
   207  	// Execute the preparatory steps for state transition which includes:
   208  	// - prepare accessList(post-berlin)
   209  	// - reset transient storage(eip 1153)
   210  	statedb.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil)
   211  
   212  	// Call the code with the given configuration.
   213  	ret, leftOverGas, err := vmenv.Call(
   214  		cfg.Origin,
   215  		address,
   216  		input,
   217  		cfg.GasLimit,
   218  		uint256.MustFromBig(cfg.Value),
   219  	)
   220  	if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil {
   221  		cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err)
   222  	}
   223  	return ret, leftOverGas, err
   224  }