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