github.com/karalabe/go-ethereum@v0.8.5/tests/helper/vm.go (about) 1 package helper 2 3 import ( 4 "errors" 5 "math/big" 6 7 "github.com/ethereum/go-ethereum/core" 8 "github.com/ethereum/go-ethereum/crypto" 9 "github.com/ethereum/go-ethereum/ethutil" 10 "github.com/ethereum/go-ethereum/state" 11 "github.com/ethereum/go-ethereum/vm" 12 ) 13 14 type Env struct { 15 depth int 16 state *state.StateDB 17 skipTransfer bool 18 initial bool 19 Gas *big.Int 20 21 origin []byte 22 parent []byte 23 coinbase []byte 24 25 number *big.Int 26 time int64 27 difficulty *big.Int 28 gasLimit *big.Int 29 30 logs state.Logs 31 } 32 33 func NewEnv(state *state.StateDB) *Env { 34 return &Env{ 35 state: state, 36 } 37 } 38 39 func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env { 40 env := NewEnv(state) 41 42 env.origin = ethutil.Hex2Bytes(exeValues["caller"]) 43 env.parent = ethutil.Hex2Bytes(envValues["previousHash"]) 44 env.coinbase = ethutil.Hex2Bytes(envValues["currentCoinbase"]) 45 env.number = ethutil.Big(envValues["currentNumber"]) 46 env.time = ethutil.Big(envValues["currentTimestamp"]).Int64() 47 env.difficulty = ethutil.Big(envValues["currentDifficulty"]) 48 env.gasLimit = ethutil.Big(envValues["currentGasLimit"]) 49 env.Gas = new(big.Int) 50 51 return env 52 } 53 54 func (self *Env) Origin() []byte { return self.origin } 55 func (self *Env) BlockNumber() *big.Int { return self.number } 56 func (self *Env) PrevHash() []byte { return self.parent } 57 func (self *Env) Coinbase() []byte { return self.coinbase } 58 func (self *Env) Time() int64 { return self.time } 59 func (self *Env) Difficulty() *big.Int { return self.difficulty } 60 func (self *Env) State() *state.StateDB { return self.state } 61 func (self *Env) GasLimit() *big.Int { return self.gasLimit } 62 func (self *Env) VmType() vm.Type { return vm.StdVmTy } 63 func (self *Env) GetHash(n uint64) []byte { 64 return crypto.Sha3([]byte(big.NewInt(int64(n)).String())) 65 } 66 func (self *Env) AddLog(log state.Log) { 67 self.logs = append(self.logs, log) 68 } 69 func (self *Env) Depth() int { return self.depth } 70 func (self *Env) SetDepth(i int) { self.depth = i } 71 func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error { 72 if self.skipTransfer { 73 // ugly hack 74 if self.initial { 75 self.initial = false 76 return nil 77 } 78 79 if from.Balance().Cmp(amount) < 0 { 80 return errors.New("Insufficient balance in account") 81 } 82 83 return nil 84 } 85 return vm.Transfer(from, to, amount) 86 } 87 88 func (self *Env) vm(addr, data []byte, gas, price, value *big.Int) *core.Execution { 89 exec := core.NewExecution(self, addr, data, gas, price, value) 90 91 return exec 92 } 93 94 func (self *Env) Call(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { 95 exe := self.vm(addr, data, gas, price, value) 96 ret, err := exe.Call(addr, caller) 97 self.Gas = exe.Gas 98 99 return ret, err 100 } 101 func (self *Env) CallCode(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) { 102 exe := self.vm(caller.Address(), data, gas, price, value) 103 return exe.Call(addr, caller) 104 } 105 106 func (self *Env) Create(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { 107 exe := self.vm(addr, data, gas, price, value) 108 return exe.Create(caller) 109 } 110 111 func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) { 112 var ( 113 to = FromHex(exec["address"]) 114 from = FromHex(exec["caller"]) 115 data = FromHex(exec["data"]) 116 gas = ethutil.Big(exec["gas"]) 117 price = ethutil.Big(exec["gasPrice"]) 118 value = ethutil.Big(exec["value"]) 119 ) 120 // Reset the pre-compiled contracts for VM tests. 121 vm.Precompiled = make(map[string]*vm.PrecompiledAccount) 122 123 caller := state.GetOrNewStateObject(from) 124 125 vmenv := NewEnvFromMap(state, env, exec) 126 vmenv.skipTransfer = true 127 vmenv.initial = true 128 ret, err := vmenv.Call(caller, to, data, gas, price, value) 129 130 return ret, vmenv.logs, vmenv.Gas, err 131 } 132 133 func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) { 134 var ( 135 keyPair, _ = crypto.NewKeyPairFromSec([]byte(ethutil.Hex2Bytes(tx["secretKey"]))) 136 to = FromHex(tx["to"]) 137 data = FromHex(tx["data"]) 138 gas = ethutil.Big(tx["gasLimit"]) 139 price = ethutil.Big(tx["gasPrice"]) 140 value = ethutil.Big(tx["value"]) 141 caddr = FromHex(env["currentCoinbase"]) 142 ) 143 144 // Set pre compiled contracts 145 vm.Precompiled = vm.PrecompiledContracts() 146 147 coinbase := statedb.GetOrNewStateObject(caddr) 148 coinbase.SetGasPool(ethutil.Big(env["currentGasLimit"])) 149 150 message := NewMessage(keyPair.Address(), to, data, value, gas, price) 151 vmenv := NewEnvFromMap(statedb, env, tx) 152 st := core.NewStateTransition(vmenv, message, coinbase) 153 vmenv.origin = keyPair.Address() 154 ret, err := st.TransitionState() 155 statedb.Update(vmenv.Gas) 156 157 return ret, vmenv.logs, vmenv.Gas, err 158 } 159 160 type Message struct { 161 from, to []byte 162 value, gas, price *big.Int 163 data []byte 164 } 165 166 func NewMessage(from, to, data []byte, value, gas, price *big.Int) Message { 167 return Message{from, to, value, gas, price, data} 168 } 169 170 func (self Message) Hash() []byte { return nil } 171 func (self Message) From() []byte { return self.from } 172 func (self Message) To() []byte { return self.to } 173 func (self Message) GasPrice() *big.Int { return self.price } 174 func (self Message) Gas() *big.Int { return self.gas } 175 func (self Message) Value() *big.Int { return self.value } 176 func (self Message) Nonce() uint64 { return 0 } 177 func (self Message) Data() []byte { return self.data }