github.com/bamzi/go-ethereum@v1.6.7-0.20170704111104-138f26c93af1/tests/util.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package tests 18 19 import ( 20 "bytes" 21 "fmt" 22 "math/big" 23 "os" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/common/math" 27 "github.com/ethereum/go-ethereum/core" 28 "github.com/ethereum/go-ethereum/core/state" 29 "github.com/ethereum/go-ethereum/core/types" 30 "github.com/ethereum/go-ethereum/core/vm" 31 "github.com/ethereum/go-ethereum/crypto" 32 "github.com/ethereum/go-ethereum/ethdb" 33 "github.com/ethereum/go-ethereum/log" 34 "github.com/ethereum/go-ethereum/params" 35 ) 36 37 var ( 38 ForceJit bool 39 EnableJit bool 40 ) 41 42 func init() { 43 log.Root().SetHandler(log.LvlFilterHandler(log.LvlCrit, log.StreamHandler(os.Stderr, log.TerminalFormat(false)))) 44 if os.Getenv("JITVM") == "true" { 45 ForceJit = true 46 EnableJit = true 47 } 48 } 49 50 func checkLogs(tlog []Log, logs []*types.Log) error { 51 if len(tlog) != len(logs) { 52 return fmt.Errorf("log length mismatch. Expected %d, got %d", len(tlog), len(logs)) 53 } else { 54 for i, log := range tlog { 55 if common.HexToAddress(log.AddressF) != logs[i].Address { 56 return fmt.Errorf("log address expected %v got %x", log.AddressF, logs[i].Address) 57 } 58 59 if !bytes.Equal(logs[i].Data, common.FromHex(log.DataF)) { 60 return fmt.Errorf("log data expected %v got %x", log.DataF, logs[i].Data) 61 } 62 63 if len(log.TopicsF) != len(logs[i].Topics) { 64 return fmt.Errorf("log topics length expected %d got %d", len(log.TopicsF), logs[i].Topics) 65 } else { 66 for j, topic := range log.TopicsF { 67 if common.HexToHash(topic) != logs[i].Topics[j] { 68 return fmt.Errorf("log topic[%d] expected %v got %x", j, topic, logs[i].Topics[j]) 69 } 70 } 71 } 72 genBloom := math.PaddedBigBytes(types.LogsBloom([]*types.Log{logs[i]}), 256) 73 74 if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) { 75 return fmt.Errorf("bloom mismatch") 76 } 77 } 78 } 79 return nil 80 } 81 82 type Account struct { 83 Balance string 84 Code string 85 Nonce string 86 Storage map[string]string 87 } 88 89 type Log struct { 90 AddressF string `json:"address"` 91 DataF string `json:"data"` 92 TopicsF []string `json:"topics"` 93 BloomF string `json:"bloom"` 94 } 95 96 func (self Log) Address() []byte { return common.Hex2Bytes(self.AddressF) } 97 func (self Log) Data() []byte { return common.Hex2Bytes(self.DataF) } 98 func (self Log) RlpData() interface{} { return nil } 99 func (self Log) Topics() [][]byte { 100 t := make([][]byte, len(self.TopicsF)) 101 for i, topic := range self.TopicsF { 102 t[i] = common.Hex2Bytes(topic) 103 } 104 return t 105 } 106 107 func makePreState(db ethdb.Database, accounts map[string]Account) *state.StateDB { 108 sdb := state.NewDatabase(db) 109 statedb, _ := state.New(common.Hash{}, sdb) 110 for addr, account := range accounts { 111 insertAccount(statedb, addr, account) 112 } 113 // Commit and re-open to start with a clean state. 114 root, _ := statedb.CommitTo(db, false) 115 statedb, _ = state.New(root, sdb) 116 return statedb 117 } 118 119 func insertAccount(state *state.StateDB, saddr string, account Account) { 120 if common.IsHex(account.Code) { 121 account.Code = account.Code[2:] 122 } 123 addr := common.HexToAddress(saddr) 124 state.SetCode(addr, common.Hex2Bytes(account.Code)) 125 state.SetNonce(addr, math.MustParseUint64(account.Nonce)) 126 state.SetBalance(addr, math.MustParseBig256(account.Balance)) 127 for a, v := range account.Storage { 128 state.SetState(addr, common.HexToHash(a), common.HexToHash(v)) 129 } 130 } 131 132 type VmEnv struct { 133 CurrentCoinbase string 134 CurrentDifficulty string 135 CurrentGasLimit string 136 CurrentNumber string 137 CurrentTimestamp interface{} 138 PreviousHash string 139 } 140 141 type VmTest struct { 142 Callcreates interface{} 143 //Env map[string]string 144 Env VmEnv 145 Exec map[string]string 146 Transaction map[string]string 147 Logs []Log 148 Gas string 149 Out string 150 Post map[string]Account 151 Pre map[string]Account 152 PostStateRoot string 153 } 154 155 func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *state.StateDB, envValues map[string]string, tx map[string]string) (*vm.EVM, core.Message) { 156 var ( 157 data = common.FromHex(tx["data"]) 158 gas = math.MustParseBig256(tx["gasLimit"]) 159 price = math.MustParseBig256(tx["gasPrice"]) 160 value = math.MustParseBig256(tx["value"]) 161 nonce = math.MustParseUint64(tx["nonce"]) 162 ) 163 164 origin := common.HexToAddress(tx["caller"]) 165 if len(tx["secretKey"]) > 0 { 166 key, _ := crypto.HexToECDSA(tx["secretKey"]) 167 origin = crypto.PubkeyToAddress(key.PublicKey) 168 } 169 170 var to *common.Address 171 if len(tx["to"]) > 2 { 172 t := common.HexToAddress(tx["to"]) 173 to = &t 174 } 175 176 msg := types.NewMessage(origin, to, nonce, value, gas, price, data, true) 177 178 initialCall := true 179 canTransfer := func(db vm.StateDB, address common.Address, amount *big.Int) bool { 180 if vmTest { 181 if initialCall { 182 initialCall = false 183 return true 184 } 185 } 186 return core.CanTransfer(db, address, amount) 187 } 188 transfer := func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) { 189 if vmTest { 190 return 191 } 192 core.Transfer(db, sender, recipient, amount) 193 } 194 195 context := vm.Context{ 196 CanTransfer: canTransfer, 197 Transfer: transfer, 198 GetHash: func(n uint64) common.Hash { 199 return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String()))) 200 }, 201 202 Origin: origin, 203 Coinbase: common.HexToAddress(envValues["currentCoinbase"]), 204 BlockNumber: math.MustParseBig256(envValues["currentNumber"]), 205 Time: math.MustParseBig256(envValues["currentTimestamp"]), 206 GasLimit: math.MustParseBig256(envValues["currentGasLimit"]), 207 Difficulty: math.MustParseBig256(envValues["currentDifficulty"]), 208 GasPrice: price, 209 } 210 if context.GasPrice == nil { 211 context.GasPrice = new(big.Int) 212 } 213 return vm.NewEVM(context, statedb, chainConfig, vm.Config{NoRecursion: vmTest}), msg 214 }