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