github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/core/vm/runtime/runtime.go (about) 1 package runtime 2 3 import ( 4 "math" 5 "math/big" 6 "time" 7 8 "github.com/quickchainproject/quickchain/common" 9 "github.com/quickchainproject/quickchain/core/state" 10 "github.com/quickchainproject/quickchain/core/vm" 11 "github.com/quickchainproject/quickchain/crypto" 12 "github.com/quickchainproject/quickchain/qctdb" 13 "github.com/quickchainproject/quickchain/params" 14 ) 15 16 // Config is a basic type specifying certain configuration flags for running 17 // the EVM. 18 type Config struct { 19 ChainConfig *params.ChainConfig 20 Difficulty *big.Int 21 Origin common.Address 22 Coinbase common.Address 23 BlockNumber *big.Int 24 Time *big.Int 25 GasLimit uint64 26 GasPrice *big.Int 27 Value *big.Int 28 Debug bool 29 EVMConfig vm.Config 30 31 State *state.StateDB 32 GetHashFn func(n uint64) common.Hash 33 } 34 35 // sets defaults on the config 36 func setDefaults(cfg *Config) { 37 if cfg.ChainConfig == nil { 38 cfg.ChainConfig = ¶ms.ChainConfig{ 39 ChainId: big.NewInt(1), 40 HomesteadBlock: new(big.Int), 41 DAOForkBlock: new(big.Int), 42 DAOForkSupport: false, 43 EIP150Block: new(big.Int), 44 EIP155Block: new(big.Int), 45 EIP158Block: new(big.Int), 46 } 47 } 48 49 if cfg.Difficulty == nil { 50 cfg.Difficulty = new(big.Int) 51 } 52 if cfg.Time == nil { 53 cfg.Time = big.NewInt(time.Now().Unix()) 54 } 55 if cfg.GasLimit == 0 { 56 cfg.GasLimit = math.MaxUint64 57 } 58 if cfg.GasPrice == nil { 59 cfg.GasPrice = new(big.Int) 60 } 61 if cfg.Value == nil { 62 cfg.Value = new(big.Int) 63 } 64 if cfg.BlockNumber == nil { 65 cfg.BlockNumber = new(big.Int) 66 } 67 if cfg.GetHashFn == nil { 68 cfg.GetHashFn = func(n uint64) common.Hash { 69 return common.BytesToHash(crypto.Keccak256([]byte(new(big.Int).SetUint64(n).String()))) 70 } 71 } 72 } 73 74 // Execute executes the code using the input as call data during the execution. 75 // It returns the EVM's return value, the new state and an error if it failed. 76 // 77 // Executes sets up a in memory, temporarily, environment for the execution of 78 // the given code. It makes sure that it's restored to it's original state afterwards. 79 func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { 80 if cfg == nil { 81 cfg = new(Config) 82 } 83 setDefaults(cfg) 84 85 if cfg.State == nil { 86 db, _ := qctdb.NewMemDatabase() 87 cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(db)) 88 } 89 var ( 90 address = common.BytesToAddress([]byte("contract")) 91 vmenv = NewEnv(cfg) 92 sender = vm.AccountRef(cfg.Origin) 93 ) 94 cfg.State.CreateAccount(address) 95 // set the receiver's (the executing contract) code for execution. 96 cfg.State.SetCode(address, code) 97 // Call the code with the given configuration. 98 ret, _, err := vmenv.Call( 99 sender, 100 common.BytesToAddress([]byte("contract")), 101 input, 102 cfg.GasLimit, 103 cfg.Value, 104 ) 105 106 return ret, cfg.State, err 107 } 108 109 // Create executes the code using the EVM create method 110 func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { 111 if cfg == nil { 112 cfg = new(Config) 113 } 114 setDefaults(cfg) 115 116 if cfg.State == nil { 117 db, _ := qctdb.NewMemDatabase() 118 cfg.State, _ = state.New(common.Hash{}, state.NewDatabase(db)) 119 } 120 var ( 121 vmenv = NewEnv(cfg) 122 sender = vm.AccountRef(cfg.Origin) 123 ) 124 125 // Call the code with the given configuration. 126 code, address, leftOverGas, err := vmenv.Create( 127 sender, 128 input, 129 cfg.GasLimit, 130 cfg.Value, 131 ) 132 return code, address, leftOverGas, err 133 } 134 135 // Call executes the code given by the contract's address. It will return the 136 // EVM's return value or an error if it failed. 137 // 138 // Call, unlike Execute, requires a config and also requires the State field to 139 // be set. 140 func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, error) { 141 setDefaults(cfg) 142 143 vmenv := NewEnv(cfg) 144 145 sender := cfg.State.GetOrNewStateObject(cfg.Origin) 146 // Call the code with the given configuration. 147 ret, leftOverGas, err := vmenv.Call( 148 sender, 149 address, 150 input, 151 cfg.GasLimit, 152 cfg.Value, 153 ) 154 155 return ret, leftOverGas, err 156 }