github.com/amazechain/amc@v0.1.3/internal/vm/runtime/runtime.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package runtime
    18  
    19  import (
    20  	"github.com/amazechain/amc/common/types"
    21  	vm2 "github.com/amazechain/amc/internal/vm"
    22  	"github.com/amazechain/amc/modules/state"
    23  	"math"
    24  	"math/big"
    25  	"time"
    26  
    27  	"github.com/amazechain/amc/common/crypto"
    28  	"github.com/amazechain/amc/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      types.Address
    38  	Coinbase    types.Address
    39  	BlockNumber *big.Int
    40  	Time        *big.Int
    41  	GasLimit    uint64
    42  	GasPrice    *uint256.Int
    43  	Value       *uint256.Int
    44  	Debug       bool
    45  	EVMConfig   vm2.Config
    46  	BaseFee     *uint256.Int
    47  
    48  	State     *state.IntraBlockState
    49  	r         state.StateReader
    50  	w         state.StateWriter
    51  	GetHashFn func(n uint64) types.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  			TangerineWhistleBlock: new(big.Int),
    61  			SpuriousDragonBlock:   new(big.Int),
    62  			ByzantiumBlock:        new(big.Int),
    63  			ConstantinopleBlock:   new(big.Int),
    64  			PetersburgBlock:       new(big.Int),
    65  			IstanbulBlock:         new(big.Int),
    66  			MuirGlacierBlock:      new(big.Int),
    67  			BerlinBlock:           new(big.Int),
    68  			LondonBlock:           new(big.Int),
    69  			ArrowGlacierBlock:     new(big.Int),
    70  			GrayGlacierBlock:      new(big.Int),
    71  			ShanghaiBlock:         new(big.Int),
    72  			CancunBlock:           new(big.Int),
    73  			PragueTime:            new(big.Int),
    74  		}
    75  	}
    76  
    77  	if cfg.Difficulty == nil {
    78  		cfg.Difficulty = new(big.Int)
    79  	}
    80  	if cfg.Time == nil {
    81  		cfg.Time = big.NewInt(time.Now().Unix())
    82  	}
    83  	if cfg.GasLimit == 0 {
    84  		cfg.GasLimit = math.MaxUint64
    85  	}
    86  	if cfg.GasPrice == nil {
    87  		cfg.GasPrice = new(uint256.Int)
    88  	}
    89  	if cfg.Value == nil {
    90  		cfg.Value = new(uint256.Int)
    91  	}
    92  	if cfg.BlockNumber == nil {
    93  		cfg.BlockNumber = new(big.Int)
    94  	}
    95  	if cfg.GetHashFn == nil {
    96  		cfg.GetHashFn = func(n uint64) types.Hash {
    97  			return types.BytesToHash(crypto.Keccak256([]byte(new(big.Int).SetUint64(n).String())))
    98  		}
    99  	}
   100  }
   101  
   102  // Execute executes the code using the input as call data during the execution.
   103  // It returns the EVM's return value, the new state and an error if it failed.
   104  //
   105  // Execute sets up an in-memory, temporary, environment for the execution of
   106  // the given code. It makes sure that it's restored to its original state afterwards.
   107  func Execute(code, input []byte, cfg *Config, bn uint64) ([]byte, *state.IntraBlockState, error) {
   108  	if cfg == nil {
   109  		cfg = new(Config)
   110  	}
   111  	setDefaults(cfg)
   112  
   113  	//if cfg.State == nil {
   114  	//	db := olddb.NewObjectDatabase(memdb.New())
   115  	//	defer db.Close()
   116  	//	cfg.r = state.NewDbStateReader(db)
   117  	//	cfg.w = state.NewDbStateWriter(db, 0)
   118  	//	cfg.kv = db
   119  	//	cfg.State = state.New(cfg.r)
   120  	//}
   121  	var (
   122  		address = types.BytesToAddress([]byte("contract"))
   123  		vmenv   = NewEnv(cfg)
   124  		sender  = vm2.AccountRef(cfg.Origin)
   125  	)
   126  	if rules := cfg.ChainConfig.Rules(vmenv.Context().BlockNumber); rules.IsBerlin {
   127  		cfg.State.PrepareAccessList(cfg.Origin, &address, vm2.ActivePrecompiles(rules), nil)
   128  	}
   129  	cfg.State.CreateAccount(address, true)
   130  	// set the receiver's (the executing contract) code for execution.
   131  	cfg.State.SetCode(address, code)
   132  	// Call the code with the given configuration.
   133  	ret, _, err := vmenv.Call(
   134  		sender,
   135  		types.BytesToAddress([]byte("contract")),
   136  		input,
   137  		cfg.GasLimit,
   138  		cfg.Value,
   139  		false, /* bailout */
   140  	)
   141  
   142  	return ret, cfg.State, err
   143  }
   144  
   145  // Create executes the code using the EVM create method
   146  func Create(input []byte, cfg *Config, blockNr uint64) ([]byte, types.Address, uint64, error) {
   147  	if cfg == nil {
   148  		cfg = new(Config)
   149  	}
   150  	setDefaults(cfg)
   151  
   152  	//if cfg.State == nil {
   153  	//	db := olddb.NewObjectDatabase(memdb.New())
   154  	//	defer db.Close()
   155  	//	cfg.r = state.NewPlainStateReader(db)
   156  	//	cfg.w = state.NewPlainStateWriter(db, ,0)
   157  	//	cfg.kv = db
   158  	//	cfg.State = state.New(cfg.r)
   159  	//}
   160  	var (
   161  		vmenv  = NewEnv(cfg)
   162  		sender = vm2.AccountRef(cfg.Origin)
   163  	)
   164  	if rules := cfg.ChainConfig.Rules(vmenv.Context().BlockNumber); rules.IsBerlin {
   165  		cfg.State.PrepareAccessList(cfg.Origin, nil, vm2.ActivePrecompiles(rules), nil)
   166  	}
   167  
   168  	// Call the code with the given configuration.
   169  	code, address, leftOverGas, err := vmenv.Create(
   170  		sender,
   171  		input,
   172  		cfg.GasLimit,
   173  		cfg.Value,
   174  	)
   175  	return code, address, leftOverGas, err
   176  }
   177  
   178  // Call executes the code given by the contract's address. It will return the
   179  // EVM's return value or an error if it failed.
   180  //
   181  // Call, unlike Execute, requires a config and also requires the State field to
   182  // be set.
   183  func Call(address types.Address, input []byte, cfg *Config) ([]byte, uint64, error) {
   184  	setDefaults(cfg)
   185  
   186  	vmenv := NewEnv(cfg)
   187  
   188  	sender := cfg.State.GetOrNewStateObject(cfg.Origin)
   189  	statedb := cfg.State
   190  	if rules := cfg.ChainConfig.Rules(vmenv.Context().BlockNumber); rules.IsBerlin {
   191  		statedb.PrepareAccessList(cfg.Origin, &address, vm2.ActivePrecompiles(rules), nil)
   192  	}
   193  
   194  	// Call the code with the given configuration.
   195  	ret, leftOverGas, err := vmenv.Call(
   196  		sender,
   197  		address,
   198  		input,
   199  		cfg.GasLimit,
   200  		cfg.Value,
   201  		false, /* bailout */
   202  	)
   203  
   204  	return ret, leftOverGas, err
   205  }