state_test_util.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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. "encoding/hex"
  19. "encoding/json"
  20. "fmt"
  21. "math/big"
  22. "strconv"
  23. "strings"
  24. "github.com/ethereum/go-ethereum/common"
  25. "github.com/ethereum/go-ethereum/common/hexutil"
  26. "github.com/ethereum/go-ethereum/common/math"
  27. "github.com/ethereum/go-ethereum/core"
  28. "github.com/ethereum/go-ethereum/core/rawdb"
  29. "github.com/ethereum/go-ethereum/core/state"
  30. "github.com/ethereum/go-ethereum/core/types"
  31. "github.com/ethereum/go-ethereum/core/vm"
  32. "github.com/ethereum/go-ethereum/crypto"
  33. "github.com/ethereum/go-ethereum/ethdb"
  34. "github.com/ethereum/go-ethereum/params"
  35. "github.com/ethereum/go-ethereum/rlp"
  36. "golang.org/x/crypto/sha3"
  37. )
  38. // StateTest checks transaction processing without block context.
  39. // See https://github.com/ethereum/EIPs/issues/176 for the test format specification.
  40. type StateTest struct {
  41. json stJSON
  42. }
  43. // StateSubtest selects a specific configuration of a General State Test.
  44. type StateSubtest struct {
  45. Fork string
  46. Index int
  47. }
  48. func (t *StateTest) UnmarshalJSON(in []byte) error {
  49. return json.Unmarshal(in, &t.json)
  50. }
  51. type stJSON struct {
  52. Env stEnv `json:"env"`
  53. Pre core.GenesisAlloc `json:"pre"`
  54. Tx stTransaction `json:"transaction"`
  55. Out hexutil.Bytes `json:"out"`
  56. Post map[string][]stPostState `json:"post"`
  57. }
  58. type stPostState struct {
  59. Root common.UnprefixedHash `json:"hash"`
  60. Logs common.UnprefixedHash `json:"logs"`
  61. Indexes struct {
  62. Data int `json:"data"`
  63. Gas int `json:"gas"`
  64. Value int `json:"value"`
  65. }
  66. }
  67. //go:generate gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
  68. type stEnv struct {
  69. Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
  70. Difficulty *big.Int `json:"currentDifficulty" gencodec:"required"`
  71. GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
  72. Number uint64 `json:"currentNumber" gencodec:"required"`
  73. Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
  74. }
  75. type stEnvMarshaling struct {
  76. Coinbase common.UnprefixedAddress
  77. Difficulty *math.HexOrDecimal256
  78. GasLimit math.HexOrDecimal64
  79. Number math.HexOrDecimal64
  80. Timestamp math.HexOrDecimal64
  81. }
  82. //go:generate gencodec -type stTransaction -field-override stTransactionMarshaling -out gen_sttransaction.go
  83. type stTransaction struct {
  84. GasPrice *big.Int `json:"gasPrice"`
  85. Nonce uint64 `json:"nonce"`
  86. To string `json:"to"`
  87. Data []string `json:"data"`
  88. GasLimit []uint64 `json:"gasLimit"`
  89. Value []string `json:"value"`
  90. PrivateKey []byte `json:"secretKey"`
  91. }
  92. type stTransactionMarshaling struct {
  93. GasPrice *math.HexOrDecimal256
  94. Nonce math.HexOrDecimal64
  95. GasLimit []math.HexOrDecimal64
  96. PrivateKey hexutil.Bytes
  97. }
  98. // getVMConfig takes a fork definition and returns a chain config.
  99. // The fork definition can be
  100. // - a plain forkname, e.g. `Byzantium`,
  101. // - a fork basename, and a list of EIPs to enable; e.g. `Byzantium+1884+1283`.
  102. func getVMConfig(forkString string) (baseConfig *params.ChainConfig, eips []int, err error) {
  103. var (
  104. splitForks = strings.Split(forkString, "+")
  105. ok bool
  106. baseName, eipsStrings = splitForks[0], splitForks[1:]
  107. )
  108. if baseConfig, ok = Forks[baseName]; !ok {
  109. return nil, nil, UnsupportedForkError{baseName}
  110. }
  111. for _, eip := range eipsStrings {
  112. if eipNum, err := strconv.Atoi(eip); err != nil {
  113. return nil, nil, fmt.Errorf("syntax error, invalid eip number %v", eipNum)
  114. } else {
  115. eips = append(eips, eipNum)
  116. }
  117. }
  118. return baseConfig, eips, nil
  119. }
  120. // Subtests returns all valid subtests of the test.
  121. func (t *StateTest) Subtests() []StateSubtest {
  122. var sub []StateSubtest
  123. for fork, pss := range t.json.Post {
  124. for i := range pss {
  125. sub = append(sub, StateSubtest{fork, i})
  126. }
  127. }
  128. return sub
  129. }
  130. // Run executes a specific subtest and verifies the post-state and logs
  131. func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateDB, error) {
  132. statedb, root, err := t.RunNoVerify(subtest, vmconfig)
  133. if err != nil {
  134. return statedb, err
  135. }
  136. post := t.json.Post[subtest.Fork][subtest.Index]
  137. // N.B: We need to do this in a two-step process, because the first Commit takes care
  138. // of suicides, and we need to touch the coinbase _after_ it has potentially suicided.
  139. if root != common.Hash(post.Root) {
  140. return statedb, fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root)
  141. }
  142. if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {
  143. return statedb, fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
  144. }
  145. return statedb, nil
  146. }
  147. // RunNoVerify runs a specific subtest and returns the statedb and post-state root
  148. func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config) (*state.StateDB, common.Hash, error) {
  149. config, eips, err := getVMConfig(subtest.Fork)
  150. if err != nil {
  151. return nil, common.Hash{}, UnsupportedForkError{subtest.Fork}
  152. }
  153. vmconfig.ExtraEips = eips
  154. block := t.genesis(config).ToBlock(nil)
  155. statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre)
  156. post := t.json.Post[subtest.Fork][subtest.Index]
  157. msg, err := t.json.Tx.toMessage(post)
  158. if err != nil {
  159. return nil, common.Hash{}, err
  160. }
  161. context := core.NewEVMContext(msg, block.Header(), nil, &t.json.Env.Coinbase)
  162. context.GetHash = vmTestBlockHash
  163. evm := vm.NewEVM(context, statedb, config, vmconfig)
  164. gaspool := new(core.GasPool)
  165. gaspool.AddGas(block.GasLimit())
  166. snapshot := statedb.Snapshot()
  167. if _, _, _, err := core.ApplyMessage(evm, msg, gaspool); err != nil {
  168. statedb.RevertToSnapshot(snapshot)
  169. }
  170. // Commit block
  171. statedb.Commit(config.IsEIP158(block.Number()))
  172. // Add 0-value mining reward. This only makes a difference in the cases
  173. // where
  174. // - the coinbase suicided, or
  175. // - there are only 'bad' transactions, which aren't executed. In those cases,
  176. // the coinbase gets no txfee, so isn't created, and thus needs to be touched
  177. statedb.AddBalance(block.Coinbase(), new(big.Int))
  178. // And _now_ get the state root
  179. root := statedb.IntermediateRoot(config.IsEIP158(block.Number()))
  180. return statedb, root, nil
  181. }
  182. func (t *StateTest) gasLimit(subtest StateSubtest) uint64 {
  183. return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas]
  184. }
  185. func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB {
  186. sdb := state.NewDatabase(db)
  187. statedb, _ := state.New(common.Hash{}, sdb)
  188. for addr, a := range accounts {
  189. statedb.SetCode(addr, a.Code)
  190. statedb.SetNonce(addr, a.Nonce)
  191. statedb.SetBalance(addr, a.Balance)
  192. for k, v := range a.Storage {
  193. statedb.SetState(addr, k, v)
  194. }
  195. }
  196. // Commit and re-open to start with a clean state.
  197. root, _ := statedb.Commit(false)
  198. statedb, _ = state.New(root, sdb)
  199. return statedb
  200. }
  201. func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
  202. return &core.Genesis{
  203. Config: config,
  204. Coinbase: t.json.Env.Coinbase,
  205. Difficulty: t.json.Env.Difficulty,
  206. GasLimit: t.json.Env.GasLimit,
  207. Number: t.json.Env.Number,
  208. Timestamp: t.json.Env.Timestamp,
  209. Alloc: t.json.Pre,
  210. }
  211. }
  212. func (tx *stTransaction) toMessage(ps stPostState) (core.Message, error) {
  213. // Derive sender from private key if present.
  214. var from common.Address
  215. if len(tx.PrivateKey) > 0 {
  216. key, err := crypto.ToECDSA(tx.PrivateKey)
  217. if err != nil {
  218. return nil, fmt.Errorf("invalid private key: %v", err)
  219. }
  220. from = crypto.PubkeyToAddress(key.PublicKey)
  221. }
  222. // Parse recipient if present.
  223. var to *common.Address
  224. if tx.To != "" {
  225. to = new(common.Address)
  226. if err := to.UnmarshalText([]byte(tx.To)); err != nil {
  227. return nil, fmt.Errorf("invalid to address: %v", err)
  228. }
  229. }
  230. // Get values specific to this post state.
  231. if ps.Indexes.Data > len(tx.Data) {
  232. return nil, fmt.Errorf("tx data index %d out of bounds", ps.Indexes.Data)
  233. }
  234. if ps.Indexes.Value > len(tx.Value) {
  235. return nil, fmt.Errorf("tx value index %d out of bounds", ps.Indexes.Value)
  236. }
  237. if ps.Indexes.Gas > len(tx.GasLimit) {
  238. return nil, fmt.Errorf("tx gas limit index %d out of bounds", ps.Indexes.Gas)
  239. }
  240. dataHex := tx.Data[ps.Indexes.Data]
  241. valueHex := tx.Value[ps.Indexes.Value]
  242. gasLimit := tx.GasLimit[ps.Indexes.Gas]
  243. // Value, Data hex encoding is messy: https://github.com/ethereum/tests/issues/203
  244. value := new(big.Int)
  245. if valueHex != "0x" {
  246. v, ok := math.ParseBig256(valueHex)
  247. if !ok {
  248. return nil, fmt.Errorf("invalid tx value %q", valueHex)
  249. }
  250. value = v
  251. }
  252. data, err := hex.DecodeString(strings.TrimPrefix(dataHex, "0x"))
  253. if err != nil {
  254. return nil, fmt.Errorf("invalid tx data %q", dataHex)
  255. }
  256. msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, tx.GasPrice, data, true)
  257. return msg, nil
  258. }
  259. func rlpHash(x interface{}) (h common.Hash) {
  260. hw := sha3.NewLegacyKeccak256()
  261. rlp.Encode(hw, x)
  262. hw.Sum(h[:0])
  263. return h
  264. }