state_test_util.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  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/state/snapshot"
  31. "github.com/ethereum/go-ethereum/core/types"
  32. "github.com/ethereum/go-ethereum/core/vm"
  33. "github.com/ethereum/go-ethereum/crypto"
  34. "github.com/ethereum/go-ethereum/ethdb"
  35. "github.com/ethereum/go-ethereum/params"
  36. "github.com/ethereum/go-ethereum/rlp"
  37. "golang.org/x/crypto/sha3"
  38. )
  39. // StateTest checks transaction processing without block context.
  40. // See https://github.com/ethereum/EIPs/issues/176 for the test format specification.
  41. type StateTest struct {
  42. json stJSON
  43. }
  44. // StateSubtest selects a specific configuration of a General State Test.
  45. type StateSubtest struct {
  46. Fork string
  47. Index int
  48. }
  49. func (t *StateTest) UnmarshalJSON(in []byte) error {
  50. return json.Unmarshal(in, &t.json)
  51. }
  52. type stJSON struct {
  53. Env stEnv `json:"env"`
  54. Pre core.GenesisAlloc `json:"pre"`
  55. Tx stTransaction `json:"transaction"`
  56. Out hexutil.Bytes `json:"out"`
  57. Post map[string][]stPostState `json:"post"`
  58. }
  59. type stPostState struct {
  60. Root common.UnprefixedHash `json:"hash"`
  61. Logs common.UnprefixedHash `json:"logs"`
  62. TxBytes hexutil.Bytes `json:"txbytes"`
  63. ExpectException string `json:"expectException"`
  64. Indexes struct {
  65. Data int `json:"data"`
  66. Gas int `json:"gas"`
  67. Value int `json:"value"`
  68. }
  69. }
  70. //go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
  71. type stEnv struct {
  72. Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
  73. Difficulty *big.Int `json:"currentDifficulty" gencodec:"optional"`
  74. Random *big.Int `json:"currentRandom" gencodec:"optional"`
  75. GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
  76. Number uint64 `json:"currentNumber" gencodec:"required"`
  77. Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
  78. BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
  79. }
  80. type stEnvMarshaling struct {
  81. Coinbase common.UnprefixedAddress
  82. Difficulty *math.HexOrDecimal256
  83. Random *math.HexOrDecimal256
  84. GasLimit math.HexOrDecimal64
  85. Number math.HexOrDecimal64
  86. Timestamp math.HexOrDecimal64
  87. BaseFee *math.HexOrDecimal256
  88. }
  89. //go:generate go run github.com/fjl/gencodec -type stTransaction -field-override stTransactionMarshaling -out gen_sttransaction.go
  90. type stTransaction struct {
  91. GasPrice *big.Int `json:"gasPrice"`
  92. MaxFeePerGas *big.Int `json:"maxFeePerGas"`
  93. MaxPriorityFeePerGas *big.Int `json:"maxPriorityFeePerGas"`
  94. Nonce uint64 `json:"nonce"`
  95. To string `json:"to"`
  96. Data []string `json:"data"`
  97. AccessLists []*types.AccessList `json:"accessLists,omitempty"`
  98. GasLimit []uint64 `json:"gasLimit"`
  99. Value []string `json:"value"`
  100. PrivateKey []byte `json:"secretKey"`
  101. }
  102. type stTransactionMarshaling struct {
  103. GasPrice *math.HexOrDecimal256
  104. MaxFeePerGas *math.HexOrDecimal256
  105. MaxPriorityFeePerGas *math.HexOrDecimal256
  106. Nonce math.HexOrDecimal64
  107. GasLimit []math.HexOrDecimal64
  108. PrivateKey hexutil.Bytes
  109. }
  110. // GetChainConfig takes a fork definition and returns a chain config.
  111. // The fork definition can be
  112. // - a plain forkname, e.g. `Byzantium`,
  113. // - a fork basename, and a list of EIPs to enable; e.g. `Byzantium+1884+1283`.
  114. func GetChainConfig(forkString string) (baseConfig *params.ChainConfig, eips []int, err error) {
  115. var (
  116. splitForks = strings.Split(forkString, "+")
  117. ok bool
  118. baseName, eipsStrings = splitForks[0], splitForks[1:]
  119. )
  120. if baseConfig, ok = Forks[baseName]; !ok {
  121. return nil, nil, UnsupportedForkError{baseName}
  122. }
  123. for _, eip := range eipsStrings {
  124. if eipNum, err := strconv.Atoi(eip); err != nil {
  125. return nil, nil, fmt.Errorf("syntax error, invalid eip number %v", eipNum)
  126. } else {
  127. if !vm.ValidEip(eipNum) {
  128. return nil, nil, fmt.Errorf("syntax error, invalid eip number %v", eipNum)
  129. }
  130. eips = append(eips, eipNum)
  131. }
  132. }
  133. return baseConfig, eips, nil
  134. }
  135. // Subtests returns all valid subtests of the test.
  136. func (t *StateTest) Subtests() []StateSubtest {
  137. var sub []StateSubtest
  138. for fork, pss := range t.json.Post {
  139. for i := range pss {
  140. sub = append(sub, StateSubtest{fork, i})
  141. }
  142. }
  143. return sub
  144. }
  145. // Run executes a specific subtest and verifies the post-state and logs
  146. func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool) (*snapshot.Tree, *state.StateDB, error) {
  147. snaps, statedb, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter)
  148. if err != nil {
  149. return snaps, statedb, err
  150. }
  151. post := t.json.Post[subtest.Fork][subtest.Index]
  152. // N.B: We need to do this in a two-step process, because the first Commit takes care
  153. // of suicides, and we need to touch the coinbase _after_ it has potentially suicided.
  154. if root != common.Hash(post.Root) {
  155. return snaps, statedb, fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root)
  156. }
  157. if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {
  158. return snaps, statedb, fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
  159. }
  160. return snaps, statedb, nil
  161. }
  162. // RunNoVerify runs a specific subtest and returns the statedb and post-state root
  163. func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool) (*snapshot.Tree, *state.StateDB, common.Hash, error) {
  164. config, eips, err := GetChainConfig(subtest.Fork)
  165. if err != nil {
  166. return nil, nil, common.Hash{}, UnsupportedForkError{subtest.Fork}
  167. }
  168. vmconfig.ExtraEips = eips
  169. block := t.genesis(config).ToBlock()
  170. snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter)
  171. var baseFee *big.Int
  172. if config.IsLondon(new(big.Int)) {
  173. baseFee = t.json.Env.BaseFee
  174. if baseFee == nil {
  175. // Retesteth uses `0x10` for genesis baseFee. Therefore, it defaults to
  176. // parent - 2 : 0xa as the basefee for 'this' context.
  177. baseFee = big.NewInt(0x0a)
  178. }
  179. }
  180. post := t.json.Post[subtest.Fork][subtest.Index]
  181. msg, err := t.json.Tx.toMessage(post, baseFee)
  182. if err != nil {
  183. return nil, nil, common.Hash{}, err
  184. }
  185. // Try to recover tx with current signer
  186. if len(post.TxBytes) != 0 {
  187. var ttx types.Transaction
  188. err := ttx.UnmarshalBinary(post.TxBytes)
  189. if err != nil {
  190. return nil, nil, common.Hash{}, err
  191. }
  192. if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil {
  193. return nil, nil, common.Hash{}, err
  194. }
  195. }
  196. // Prepare the EVM.
  197. txContext := core.NewEVMTxContext(msg)
  198. context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
  199. context.GetHash = vmTestBlockHash
  200. context.BaseFee = baseFee
  201. context.Random = nil
  202. if config.IsLondon(new(big.Int)) && t.json.Env.Random != nil {
  203. rnd := common.BigToHash(t.json.Env.Random)
  204. context.Random = &rnd
  205. context.Difficulty = big.NewInt(0)
  206. }
  207. evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
  208. // Execute the message.
  209. snapshot := statedb.Snapshot()
  210. gaspool := new(core.GasPool)
  211. gaspool.AddGas(block.GasLimit())
  212. if _, err := core.ApplyMessage(evm, msg, gaspool); err != nil {
  213. statedb.RevertToSnapshot(snapshot)
  214. }
  215. // Add 0-value mining reward. This only makes a difference in the cases
  216. // where
  217. // - the coinbase suicided, or
  218. // - there are only 'bad' transactions, which aren't executed. In those cases,
  219. // the coinbase gets no txfee, so isn't created, and thus needs to be touched
  220. statedb.AddBalance(block.Coinbase(), new(big.Int))
  221. // Commit block
  222. statedb.Commit(config.IsEIP158(block.Number()))
  223. // And _now_ get the state root
  224. root := statedb.IntermediateRoot(config.IsEIP158(block.Number()))
  225. return snaps, statedb, root, nil
  226. }
  227. func (t *StateTest) gasLimit(subtest StateSubtest) uint64 {
  228. return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas]
  229. }
  230. func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool) (*snapshot.Tree, *state.StateDB) {
  231. sdb := state.NewDatabase(db)
  232. statedb, _ := state.New(common.Hash{}, sdb, nil)
  233. for addr, a := range accounts {
  234. statedb.SetCode(addr, a.Code)
  235. statedb.SetNonce(addr, a.Nonce)
  236. statedb.SetBalance(addr, a.Balance)
  237. for k, v := range a.Storage {
  238. statedb.SetState(addr, k, v)
  239. }
  240. }
  241. // Commit and re-open to start with a clean state.
  242. root, _ := statedb.Commit(false)
  243. var snaps *snapshot.Tree
  244. if snapshotter {
  245. snaps, _ = snapshot.New(db, sdb.TrieDB(), 1, root, false, true, false)
  246. }
  247. statedb, _ = state.New(root, sdb, snaps)
  248. return snaps, statedb
  249. }
  250. func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
  251. genesis := &core.Genesis{
  252. Config: config,
  253. Coinbase: t.json.Env.Coinbase,
  254. Difficulty: t.json.Env.Difficulty,
  255. GasLimit: t.json.Env.GasLimit,
  256. Number: t.json.Env.Number,
  257. Timestamp: t.json.Env.Timestamp,
  258. Alloc: t.json.Pre,
  259. }
  260. if t.json.Env.Random != nil {
  261. // Post-Merge
  262. genesis.Mixhash = common.BigToHash(t.json.Env.Random)
  263. genesis.Difficulty = big.NewInt(0)
  264. }
  265. return genesis
  266. }
  267. func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (core.Message, error) {
  268. // Derive sender from private key if present.
  269. var from common.Address
  270. if len(tx.PrivateKey) > 0 {
  271. key, err := crypto.ToECDSA(tx.PrivateKey)
  272. if err != nil {
  273. return nil, fmt.Errorf("invalid private key: %v", err)
  274. }
  275. from = crypto.PubkeyToAddress(key.PublicKey)
  276. }
  277. // Parse recipient if present.
  278. var to *common.Address
  279. if tx.To != "" {
  280. to = new(common.Address)
  281. if err := to.UnmarshalText([]byte(tx.To)); err != nil {
  282. return nil, fmt.Errorf("invalid to address: %v", err)
  283. }
  284. }
  285. // Get values specific to this post state.
  286. if ps.Indexes.Data > len(tx.Data) {
  287. return nil, fmt.Errorf("tx data index %d out of bounds", ps.Indexes.Data)
  288. }
  289. if ps.Indexes.Value > len(tx.Value) {
  290. return nil, fmt.Errorf("tx value index %d out of bounds", ps.Indexes.Value)
  291. }
  292. if ps.Indexes.Gas > len(tx.GasLimit) {
  293. return nil, fmt.Errorf("tx gas limit index %d out of bounds", ps.Indexes.Gas)
  294. }
  295. dataHex := tx.Data[ps.Indexes.Data]
  296. valueHex := tx.Value[ps.Indexes.Value]
  297. gasLimit := tx.GasLimit[ps.Indexes.Gas]
  298. // Value, Data hex encoding is messy: https://github.com/ethereum/tests/issues/203
  299. value := new(big.Int)
  300. if valueHex != "0x" {
  301. v, ok := math.ParseBig256(valueHex)
  302. if !ok {
  303. return nil, fmt.Errorf("invalid tx value %q", valueHex)
  304. }
  305. value = v
  306. }
  307. data, err := hex.DecodeString(strings.TrimPrefix(dataHex, "0x"))
  308. if err != nil {
  309. return nil, fmt.Errorf("invalid tx data %q", dataHex)
  310. }
  311. var accessList types.AccessList
  312. if tx.AccessLists != nil && tx.AccessLists[ps.Indexes.Data] != nil {
  313. accessList = *tx.AccessLists[ps.Indexes.Data]
  314. }
  315. // If baseFee provided, set gasPrice to effectiveGasPrice.
  316. gasPrice := tx.GasPrice
  317. if baseFee != nil {
  318. if tx.MaxFeePerGas == nil {
  319. tx.MaxFeePerGas = gasPrice
  320. }
  321. if tx.MaxFeePerGas == nil {
  322. tx.MaxFeePerGas = new(big.Int)
  323. }
  324. if tx.MaxPriorityFeePerGas == nil {
  325. tx.MaxPriorityFeePerGas = tx.MaxFeePerGas
  326. }
  327. gasPrice = math.BigMin(new(big.Int).Add(tx.MaxPriorityFeePerGas, baseFee),
  328. tx.MaxFeePerGas)
  329. }
  330. if gasPrice == nil {
  331. return nil, fmt.Errorf("no gas price provided")
  332. }
  333. msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, gasPrice,
  334. tx.MaxFeePerGas, tx.MaxPriorityFeePerGas, data, accessList, false)
  335. return msg, nil
  336. }
  337. func rlpHash(x interface{}) (h common.Hash) {
  338. hw := sha3.NewLegacyKeccak256()
  339. rlp.Encode(hw, x)
  340. hw.Sum(h[:0])
  341. return h
  342. }
  343. func vmTestBlockHash(n uint64) common.Hash {
  344. return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
  345. }