github.com/ontio/ontology@v1.14.4/vm/evm/runtime/runtime.go (about)

     1  // Copyright (C) 2021 The Ontology 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  	"time"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/crypto"
    26  	"github.com/holiman/uint256"
    27  	"github.com/ontio/ontology/core/store/leveldbstore"
    28  	"github.com/ontio/ontology/core/store/overlaydb"
    29  	"github.com/ontio/ontology/smartcontract/service/native/ong"
    30  	"github.com/ontio/ontology/smartcontract/storage"
    31  	"github.com/ontio/ontology/vm/evm"
    32  	"github.com/ontio/ontology/vm/evm/params"
    33  )
    34  
    35  // Config is a basic type specifying certain configuration flags for running
    36  // the EVM.
    37  type Config struct {
    38  	ChainConfig *params.ChainConfig
    39  	Difficulty  *big.Int
    40  	Origin      common.Address
    41  	Coinbase    common.Address
    42  	BlockNumber *big.Int
    43  	Time        *big.Int
    44  	GasLimit    uint64
    45  	GasPrice    *big.Int
    46  	Value       *big.Int
    47  	Debug       bool
    48  	EVMConfig   evm.Config
    49  
    50  	State     *storage.StateDB
    51  	GetHashFn func(n uint64) common.Hash
    52  }
    53  
    54  // sets defaults on the config
    55  func setDefaults(cfg *Config) {
    56  	if cfg.ChainConfig == nil {
    57  		cfg.ChainConfig = &params.ChainConfig{
    58  			ChainID:             big.NewInt(1),
    59  			HomesteadBlock:      new(big.Int),
    60  			DAOForkBlock:        new(big.Int),
    61  			DAOForkSupport:      false,
    62  			EIP150Block:         new(big.Int),
    63  			EIP155Block:         new(big.Int),
    64  			EIP158Block:         new(big.Int),
    65  			ByzantiumBlock:      new(big.Int),
    66  			ConstantinopleBlock: new(big.Int),
    67  			PetersburgBlock:     new(big.Int),
    68  			IstanbulBlock:       new(big.Int),
    69  			MuirGlacierBlock:    new(big.Int),
    70  			YoloV2Block:         nil,
    71  		}
    72  	}
    73  
    74  	if cfg.Difficulty == nil {
    75  		cfg.Difficulty = new(big.Int)
    76  	}
    77  	if cfg.Time == nil {
    78  		cfg.Time = big.NewInt(time.Now().Unix())
    79  	}
    80  	if cfg.GasLimit == 0 {
    81  		cfg.GasLimit = math.MaxUint64
    82  	}
    83  	if cfg.GasPrice == nil {
    84  		cfg.GasPrice = new(big.Int)
    85  	}
    86  	if cfg.Value == nil {
    87  		cfg.Value = new(big.Int)
    88  	}
    89  	if cfg.BlockNumber == nil {
    90  		cfg.BlockNumber = new(big.Int)
    91  	}
    92  	if cfg.GetHashFn == nil {
    93  		cfg.GetHashFn = func(n uint64) common.Hash {
    94  			return common.BytesToHash(crypto.Keccak256([]byte(new(big.Int).SetUint64(n).String())))
    95  		}
    96  	}
    97  }
    98  
    99  // Execute executes the code using the input as call data during the execution.
   100  // It returns the EVM's return value, the new state and an error if it failed.
   101  //
   102  // Execute sets up an in-memory, temporary, environment for the execution of
   103  // the given code. It makes sure that it's restored to its original state afterwards.
   104  func Execute(code, input []byte, cfg *Config) ([]byte, *storage.StateDB, error) {
   105  	if cfg == nil {
   106  		cfg = new(Config)
   107  	}
   108  	setDefaults(cfg)
   109  
   110  	if cfg.State == nil {
   111  		db := storage.NewCacheDB(overlaydb.NewOverlayDB(leveldbstore.NewMemLevelDBStore()))
   112  		cfg.State = storage.NewStateDB(db, common.Hash{}, common.Hash{}, ong.OngBalanceHandle{})
   113  	}
   114  	var (
   115  		address = common.BytesToAddress([]byte("contract"))
   116  		vmenv   = NewEnv(cfg)
   117  		sender  = evm.AccountRef(cfg.Origin)
   118  	)
   119  
   120  	cfg.State.CreateAccount(address)
   121  	// set the receiver's (the executing contract) code for execution.
   122  	cfg.State.SetCode(address, code)
   123  	// Call the code with the given configuration.
   124  	ret, _, err := vmenv.Call(
   125  		sender,
   126  		common.BytesToAddress([]byte("contract")),
   127  		input,
   128  		cfg.GasLimit,
   129  		cfg.Value,
   130  	)
   131  
   132  	return ret, cfg.State, err
   133  }
   134  
   135  // Create executes the code using the EVM create method
   136  func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) {
   137  	if cfg == nil {
   138  		cfg = new(Config)
   139  	}
   140  	setDefaults(cfg)
   141  
   142  	if cfg.State == nil {
   143  		db := storage.NewCacheDB(overlaydb.NewOverlayDB(leveldbstore.NewMemLevelDBStore()))
   144  		cfg.State = storage.NewStateDB(db, common.Hash{}, common.Hash{}, ong.OngBalanceHandle{})
   145  	}
   146  	var (
   147  		vmenv  = NewEnv(cfg)
   148  		sender = evm.AccountRef(cfg.Origin)
   149  	)
   150  
   151  	// Call the code with the given configuration.
   152  	code, address, leftOverGas, err := vmenv.Create(
   153  		sender,
   154  		input,
   155  		cfg.GasLimit,
   156  		cfg.Value,
   157  	)
   158  	return code, address, leftOverGas, err
   159  }
   160  
   161  // Create2 executes the code using the EVM create2 method
   162  func Create2(input []byte, cfg *Config, salt *uint256.Int) ([]byte, common.Address, uint64, error) {
   163  	if cfg == nil {
   164  		cfg = new(Config)
   165  	}
   166  	setDefaults(cfg)
   167  
   168  	if cfg.State == nil {
   169  		db := storage.NewCacheDB(overlaydb.NewOverlayDB(leveldbstore.NewMemLevelDBStore()))
   170  		cfg.State = storage.NewStateDB(db, common.Hash{}, common.Hash{}, ong.OngBalanceHandle{})
   171  	}
   172  	var (
   173  		vmenv  = NewEnv(cfg)
   174  		sender = evm.AccountRef(cfg.Origin)
   175  	)
   176  
   177  	// Call the code with the given configuration.
   178  	code, address, leftOverGas, err := vmenv.Create2(
   179  		sender,
   180  		input,
   181  		cfg.GasLimit,
   182  		cfg.Value,
   183  		salt,
   184  	)
   185  	return code, address, leftOverGas, err
   186  }
   187  
   188  // Call executes the code given by the contract's address. It will return the
   189  // EVM's return value or an error if it failed.
   190  //
   191  // Call, unlike Execute, requires a config and also requires the State field to
   192  // be set.
   193  func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, error) {
   194  	setDefaults(cfg)
   195  
   196  	vmenv := NewEnv(cfg)
   197  	sender := evm.AccountRef(cfg.Origin)
   198  
   199  	// Call the code with the given configuration.
   200  	ret, leftOverGas, err := vmenv.Call(
   201  		sender,
   202  		address,
   203  		input,
   204  		cfg.GasLimit,
   205  		cfg.Value,
   206  	)
   207  
   208  	return ret, leftOverGas, err
   209  }