vm_test_util.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. package tests
  17. import (
  18. "bytes"
  19. "fmt"
  20. "io"
  21. "math/big"
  22. "strconv"
  23. "testing"
  24. "github.com/ethereum/go-ethereum/common"
  25. "github.com/ethereum/go-ethereum/common/math"
  26. "github.com/ethereum/go-ethereum/core/state"
  27. "github.com/ethereum/go-ethereum/core/types"
  28. "github.com/ethereum/go-ethereum/core/vm"
  29. "github.com/ethereum/go-ethereum/ethdb"
  30. "github.com/ethereum/go-ethereum/log"
  31. "github.com/ethereum/go-ethereum/params"
  32. )
  33. func RunVmTestWithReader(r io.Reader, skipTests []string) error {
  34. tests := make(map[string]VmTest)
  35. err := readJson(r, &tests)
  36. if err != nil {
  37. return err
  38. }
  39. if err != nil {
  40. return err
  41. }
  42. if err := runVmTests(tests, skipTests); err != nil {
  43. return err
  44. }
  45. return nil
  46. }
  47. type bconf struct {
  48. name string
  49. precomp bool
  50. jit bool
  51. }
  52. func BenchVmTest(p string, conf bconf, b *testing.B) error {
  53. tests := make(map[string]VmTest)
  54. err := readJsonFile(p, &tests)
  55. if err != nil {
  56. return err
  57. }
  58. test, ok := tests[conf.name]
  59. if !ok {
  60. return fmt.Errorf("test not found: %s", conf.name)
  61. }
  62. env := make(map[string]string)
  63. env["currentCoinbase"] = test.Env.CurrentCoinbase
  64. env["currentDifficulty"] = test.Env.CurrentDifficulty
  65. env["currentGasLimit"] = test.Env.CurrentGasLimit
  66. env["currentNumber"] = test.Env.CurrentNumber
  67. env["previousHash"] = test.Env.PreviousHash
  68. if n, ok := test.Env.CurrentTimestamp.(float64); ok {
  69. env["currentTimestamp"] = strconv.Itoa(int(n))
  70. } else {
  71. env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
  72. }
  73. /*
  74. if conf.precomp {
  75. program := vm.NewProgram(test.code)
  76. err := vm.AttachProgram(program)
  77. if err != nil {
  78. return err
  79. }
  80. }
  81. */
  82. b.ResetTimer()
  83. for i := 0; i < b.N; i++ {
  84. benchVmTest(test, env, b)
  85. }
  86. return nil
  87. }
  88. func benchVmTest(test VmTest, env map[string]string, b *testing.B) {
  89. b.StopTimer()
  90. db, _ := ethdb.NewMemDatabase()
  91. statedb := makePreState(db, test.Pre)
  92. b.StartTimer()
  93. RunVm(statedb, env, test.Exec)
  94. }
  95. func RunVmTest(p string, skipTests []string) error {
  96. tests := make(map[string]VmTest)
  97. err := readJsonFile(p, &tests)
  98. if err != nil {
  99. return err
  100. }
  101. if err := runVmTests(tests, skipTests); err != nil {
  102. return err
  103. }
  104. return nil
  105. }
  106. func runVmTests(tests map[string]VmTest, skipTests []string) error {
  107. skipTest := make(map[string]bool, len(skipTests))
  108. for _, name := range skipTests {
  109. skipTest[name] = true
  110. }
  111. for name, test := range tests {
  112. if skipTest[name] /*|| name != "exp0"*/ {
  113. log.Info(fmt.Sprint("Skipping VM test", name))
  114. continue
  115. }
  116. if err := runVmTest(test); err != nil {
  117. return fmt.Errorf("%s %s", name, err.Error())
  118. }
  119. log.Info(fmt.Sprint("VM test passed: ", name))
  120. //fmt.Println(string(statedb.Dump()))
  121. }
  122. return nil
  123. }
  124. func runVmTest(test VmTest) error {
  125. db, _ := ethdb.NewMemDatabase()
  126. statedb := makePreState(db, test.Pre)
  127. // XXX Yeah, yeah...
  128. env := make(map[string]string)
  129. env["currentCoinbase"] = test.Env.CurrentCoinbase
  130. env["currentDifficulty"] = test.Env.CurrentDifficulty
  131. env["currentGasLimit"] = test.Env.CurrentGasLimit
  132. env["currentNumber"] = test.Env.CurrentNumber
  133. env["previousHash"] = test.Env.PreviousHash
  134. if n, ok := test.Env.CurrentTimestamp.(float64); ok {
  135. env["currentTimestamp"] = strconv.Itoa(int(n))
  136. } else {
  137. env["currentTimestamp"] = test.Env.CurrentTimestamp.(string)
  138. }
  139. var (
  140. ret []byte
  141. gas *big.Int
  142. err error
  143. logs []*types.Log
  144. )
  145. ret, logs, gas, err = RunVm(statedb, env, test.Exec)
  146. // Compare expected and actual return
  147. rexp := common.FromHex(test.Out)
  148. if !bytes.Equal(rexp, ret) {
  149. return fmt.Errorf("return failed. Expected %x, got %x\n", rexp, ret)
  150. }
  151. // Check gas usage
  152. if len(test.Gas) == 0 && err == nil {
  153. return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successful")
  154. } else {
  155. gexp := math.MustParseBig256(test.Gas)
  156. if gexp.Cmp(gas) != 0 {
  157. return fmt.Errorf("gas failed. Expected %v, got %v\n", gexp, gas)
  158. }
  159. }
  160. // check post state
  161. for address, account := range test.Post {
  162. accountAddr := common.HexToAddress(address)
  163. if !statedb.Exist(accountAddr) {
  164. continue
  165. }
  166. for addr, value := range account.Storage {
  167. v := statedb.GetState(accountAddr, common.HexToHash(addr))
  168. vexp := common.HexToHash(value)
  169. if v != vexp {
  170. return fmt.Errorf("(%x: %s) storage failed. Expected %x, got %x (%v %v)\n", addr[:4], addr, vexp, v, vexp.Big(), v.Big())
  171. }
  172. }
  173. }
  174. // check logs
  175. if len(test.Logs) > 0 {
  176. lerr := checkLogs(test.Logs, logs)
  177. if lerr != nil {
  178. return lerr
  179. }
  180. }
  181. return nil
  182. }
  183. func RunVm(statedb *state.StateDB, env, exec map[string]string) ([]byte, []*types.Log, *big.Int, error) {
  184. chainConfig := &params.ChainConfig{
  185. HomesteadBlock: params.MainnetChainConfig.HomesteadBlock,
  186. DAOForkBlock: params.MainnetChainConfig.DAOForkBlock,
  187. DAOForkSupport: true,
  188. }
  189. var (
  190. to = common.HexToAddress(exec["address"])
  191. from = common.HexToAddress(exec["caller"])
  192. data = common.FromHex(exec["data"])
  193. gas = math.MustParseBig256(exec["gas"])
  194. value = math.MustParseBig256(exec["value"])
  195. )
  196. caller := statedb.GetOrNewStateObject(from)
  197. vm.PrecompiledContracts = make(map[common.Address]vm.PrecompiledContract)
  198. environment, _ := NewEVMEnvironment(true, chainConfig, statedb, env, exec)
  199. ret, g, err := environment.Call(caller, to, data, gas.Uint64(), value)
  200. return ret, statedb.Logs(), new(big.Int).SetUint64(g), err
  201. }