github.com/ylsGit/go-ethereum@v1.6.5/tests/state_test_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 "io" 23 "math/big" 24 "strconv" 25 "strings" 26 "testing" 27 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/common/math" 30 "github.com/ethereum/go-ethereum/core" 31 "github.com/ethereum/go-ethereum/core/state" 32 "github.com/ethereum/go-ethereum/core/types" 33 "github.com/ethereum/go-ethereum/ethdb" 34 "github.com/ethereum/go-ethereum/log" 35 "github.com/ethereum/go-ethereum/params" 36 ) 37 38 func RunStateTestWithReader(chainConfig *params.ChainConfig, r io.Reader, skipTests []string) error { 39 tests := make(map[string]VmTest) 40 if err := readJson(r, &tests); err != nil { 41 return err 42 } 43 44 if err := runStateTests(chainConfig, tests, skipTests); err != nil { 45 return err 46 } 47 48 return nil 49 } 50 51 func RunStateTest(chainConfig *params.ChainConfig, p string, skipTests []string) error { 52 tests := make(map[string]VmTest) 53 if err := readJsonFile(p, &tests); err != nil { 54 return err 55 } 56 57 if err := runStateTests(chainConfig, tests, skipTests); err != nil { 58 return err 59 } 60 61 return nil 62 63 } 64 65 func BenchStateTest(chainConfig *params.ChainConfig, p string, conf bconf, b *testing.B) error { 66 tests := make(map[string]VmTest) 67 if err := readJsonFile(p, &tests); err != nil { 68 return err 69 } 70 test, ok := tests[conf.name] 71 if !ok { 72 return fmt.Errorf("test not found: %s", conf.name) 73 } 74 75 // XXX Yeah, yeah... 76 env := make(map[string]string) 77 env["currentCoinbase"] = test.Env.CurrentCoinbase 78 env["currentDifficulty"] = test.Env.CurrentDifficulty 79 env["currentGasLimit"] = test.Env.CurrentGasLimit 80 env["currentNumber"] = test.Env.CurrentNumber 81 env["previousHash"] = test.Env.PreviousHash 82 if n, ok := test.Env.CurrentTimestamp.(float64); ok { 83 env["currentTimestamp"] = strconv.Itoa(int(n)) 84 } else { 85 env["currentTimestamp"] = test.Env.CurrentTimestamp.(string) 86 } 87 88 b.ResetTimer() 89 for i := 0; i < b.N; i++ { 90 benchStateTest(chainConfig, test, env, b) 91 } 92 93 return nil 94 } 95 96 func benchStateTest(chainConfig *params.ChainConfig, test VmTest, env map[string]string, b *testing.B) { 97 b.StopTimer() 98 db, _ := ethdb.NewMemDatabase() 99 statedb := makePreState(db, test.Pre) 100 b.StartTimer() 101 102 RunState(chainConfig, statedb, env, test.Exec) 103 } 104 105 func runStateTests(chainConfig *params.ChainConfig, tests map[string]VmTest, skipTests []string) error { 106 skipTest := make(map[string]bool, len(skipTests)) 107 for _, name := range skipTests { 108 skipTest[name] = true 109 } 110 111 for name, test := range tests { 112 if skipTest[name] /*|| name != "JUMPDEST_Attack"*/ { 113 log.Info(fmt.Sprint("Skipping state test", name)) 114 continue 115 } 116 117 //fmt.Println("StateTest:", name) 118 if err := runStateTest(chainConfig, test); err != nil { 119 return fmt.Errorf("%s: %s\n", name, err.Error()) 120 } 121 122 //log.Info(fmt.Sprint("State test passed: ", name)) 123 //fmt.Println(string(statedb.Dump())) 124 } 125 return nil 126 127 } 128 129 func runStateTest(chainConfig *params.ChainConfig, test VmTest) error { 130 db, _ := ethdb.NewMemDatabase() 131 statedb := makePreState(db, test.Pre) 132 133 // XXX Yeah, yeah... 134 env := make(map[string]string) 135 env["currentCoinbase"] = test.Env.CurrentCoinbase 136 env["currentDifficulty"] = test.Env.CurrentDifficulty 137 env["currentGasLimit"] = test.Env.CurrentGasLimit 138 env["currentNumber"] = test.Env.CurrentNumber 139 env["previousHash"] = test.Env.PreviousHash 140 if n, ok := test.Env.CurrentTimestamp.(float64); ok { 141 env["currentTimestamp"] = strconv.Itoa(int(n)) 142 } else { 143 env["currentTimestamp"] = test.Env.CurrentTimestamp.(string) 144 } 145 146 var ( 147 ret []byte 148 // gas *big.Int 149 // err error 150 logs []*types.Log 151 ) 152 153 ret, logs, _, _ = RunState(chainConfig, statedb, env, test.Transaction) 154 155 // Compare expected and actual return 156 var rexp []byte 157 if strings.HasPrefix(test.Out, "#") { 158 n, _ := strconv.Atoi(test.Out[1:]) 159 rexp = make([]byte, n) 160 } else { 161 rexp = common.FromHex(test.Out) 162 } 163 if !bytes.Equal(rexp, ret) { 164 return fmt.Errorf("return failed. Expected %x, got %x\n", rexp, ret) 165 } 166 167 // check post state 168 for addr, account := range test.Post { 169 address := common.HexToAddress(addr) 170 if !statedb.Exist(address) { 171 return fmt.Errorf("did not find expected post-state account: %s", addr) 172 } 173 174 if balance := statedb.GetBalance(address); balance.Cmp(math.MustParseBig256(account.Balance)) != 0 { 175 return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", address[:4], math.MustParseBig256(account.Balance), balance) 176 } 177 178 if nonce := statedb.GetNonce(address); nonce != math.MustParseUint64(account.Nonce) { 179 return fmt.Errorf("(%x) nonce failed. Expected: %v have: %v\n", address[:4], account.Nonce, nonce) 180 } 181 182 for addr, value := range account.Storage { 183 v := statedb.GetState(address, common.HexToHash(addr)) 184 vexp := common.HexToHash(value) 185 186 if v != vexp { 187 return fmt.Errorf("storage failed:\n%x: %s:\nexpected: %x\nhave: %x\n(%v %v)\n", address[:4], addr, vexp, v, vexp.Big(), v.Big()) 188 } 189 } 190 } 191 192 root, _ := statedb.Commit(false) 193 if common.HexToHash(test.PostStateRoot) != root { 194 return fmt.Errorf("Post state root error. Expected: %s have: %x", test.PostStateRoot, root) 195 } 196 197 // check logs 198 if len(test.Logs) > 0 { 199 if err := checkLogs(test.Logs, logs); err != nil { 200 return err 201 } 202 } 203 204 return nil 205 } 206 207 func RunState(chainConfig *params.ChainConfig, statedb *state.StateDB, env, tx map[string]string) ([]byte, []*types.Log, *big.Int, error) { 208 environment, msg := NewEVMEnvironment(false, chainConfig, statedb, env, tx) 209 gaspool := new(core.GasPool).AddGas(math.MustParseBig256(env["currentGasLimit"])) 210 211 root, _ := statedb.Commit(false) 212 statedb.Reset(root) 213 214 snapshot := statedb.Snapshot() 215 216 ret, gasUsed, err := core.ApplyMessage(environment, msg, gaspool) 217 if err != nil { 218 statedb.RevertToSnapshot(snapshot) 219 } 220 statedb.Commit(chainConfig.IsEIP158(environment.Context.BlockNumber)) 221 222 return ret, statedb.Logs(), gasUsed, err 223 }