api_test.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. // Copyright 2021 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 tracers
  17. import (
  18. "bytes"
  19. "context"
  20. "crypto/ecdsa"
  21. "encoding/json"
  22. "errors"
  23. "fmt"
  24. "math/big"
  25. "reflect"
  26. "sort"
  27. "testing"
  28. "time"
  29. "github.com/ethereum/go-ethereum/common"
  30. "github.com/ethereum/go-ethereum/common/hexutil"
  31. "github.com/ethereum/go-ethereum/consensus"
  32. "github.com/ethereum/go-ethereum/consensus/ethash"
  33. "github.com/ethereum/go-ethereum/core"
  34. "github.com/ethereum/go-ethereum/core/rawdb"
  35. "github.com/ethereum/go-ethereum/core/state"
  36. "github.com/ethereum/go-ethereum/core/types"
  37. "github.com/ethereum/go-ethereum/core/vm"
  38. "github.com/ethereum/go-ethereum/crypto"
  39. "github.com/ethereum/go-ethereum/eth/tracers/logger"
  40. "github.com/ethereum/go-ethereum/ethdb"
  41. "github.com/ethereum/go-ethereum/internal/ethapi"
  42. "github.com/ethereum/go-ethereum/params"
  43. "github.com/ethereum/go-ethereum/rpc"
  44. )
  45. var (
  46. errStateNotFound = errors.New("state not found")
  47. errBlockNotFound = errors.New("block not found")
  48. errTransactionNotFound = errors.New("transaction not found")
  49. )
  50. type testBackend struct {
  51. chainConfig *params.ChainConfig
  52. engine consensus.Engine
  53. chaindb ethdb.Database
  54. chain *core.BlockChain
  55. }
  56. func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend {
  57. backend := &testBackend{
  58. chainConfig: params.TestChainConfig,
  59. engine: ethash.NewFaker(),
  60. chaindb: rawdb.NewMemoryDatabase(),
  61. }
  62. // Generate blocks for testing
  63. gspec.Config = backend.chainConfig
  64. var (
  65. gendb = rawdb.NewMemoryDatabase()
  66. genesis = gspec.MustCommit(gendb)
  67. )
  68. blocks, _ := core.GenerateChain(backend.chainConfig, genesis, backend.engine, gendb, n, generator)
  69. // Import the canonical chain
  70. gspec.MustCommit(backend.chaindb)
  71. cacheConfig := &core.CacheConfig{
  72. TrieCleanLimit: 256,
  73. TrieDirtyLimit: 256,
  74. TrieTimeLimit: 5 * time.Minute,
  75. SnapshotLimit: 0,
  76. TrieDirtyDisabled: true, // Archive mode
  77. }
  78. chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, backend.chainConfig, backend.engine, vm.Config{}, nil, nil)
  79. if err != nil {
  80. t.Fatalf("failed to create tester chain: %v", err)
  81. }
  82. if n, err := chain.InsertChain(blocks); err != nil {
  83. t.Fatalf("block %d: failed to insert into chain: %v", n, err)
  84. }
  85. backend.chain = chain
  86. return backend
  87. }
  88. func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
  89. return b.chain.GetHeaderByHash(hash), nil
  90. }
  91. func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
  92. if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber {
  93. return b.chain.CurrentHeader(), nil
  94. }
  95. return b.chain.GetHeaderByNumber(uint64(number)), nil
  96. }
  97. func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
  98. return b.chain.GetBlockByHash(hash), nil
  99. }
  100. func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
  101. if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber {
  102. return b.chain.CurrentBlock(), nil
  103. }
  104. return b.chain.GetBlockByNumber(uint64(number)), nil
  105. }
  106. func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
  107. tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash)
  108. if tx == nil {
  109. return nil, common.Hash{}, 0, 0, errTransactionNotFound
  110. }
  111. return tx, hash, blockNumber, index, nil
  112. }
  113. func (b *testBackend) RPCGasCap() uint64 {
  114. return 25000000
  115. }
  116. func (b *testBackend) ChainConfig() *params.ChainConfig {
  117. return b.chainConfig
  118. }
  119. func (b *testBackend) Engine() consensus.Engine {
  120. return b.engine
  121. }
  122. func (b *testBackend) ChainDb() ethdb.Database {
  123. return b.chaindb
  124. }
  125. func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (*state.StateDB, error) {
  126. statedb, err := b.chain.StateAt(block.Root())
  127. if err != nil {
  128. return nil, errStateNotFound
  129. }
  130. return statedb, nil
  131. }
  132. func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
  133. parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1)
  134. if parent == nil {
  135. return nil, vm.BlockContext{}, nil, errBlockNotFound
  136. }
  137. statedb, err := b.chain.StateAt(parent.Root())
  138. if err != nil {
  139. return nil, vm.BlockContext{}, nil, errStateNotFound
  140. }
  141. if txIndex == 0 && len(block.Transactions()) == 0 {
  142. return nil, vm.BlockContext{}, statedb, nil
  143. }
  144. // Recompute transactions up to the target index.
  145. signer := types.MakeSigner(b.chainConfig, block.Number())
  146. for idx, tx := range block.Transactions() {
  147. msg, _ := tx.AsMessage(signer, block.BaseFee())
  148. txContext := core.NewEVMTxContext(msg)
  149. context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
  150. if idx == txIndex {
  151. return msg, context, statedb, nil
  152. }
  153. vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{})
  154. if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
  155. return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
  156. }
  157. statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
  158. }
  159. return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
  160. }
  161. func TestTraceCall(t *testing.T) {
  162. t.Parallel()
  163. // Initialize test accounts
  164. accounts := newAccounts(3)
  165. genesis := &core.Genesis{Alloc: core.GenesisAlloc{
  166. accounts[0].addr: {Balance: big.NewInt(params.Ether)},
  167. accounts[1].addr: {Balance: big.NewInt(params.Ether)},
  168. accounts[2].addr: {Balance: big.NewInt(params.Ether)},
  169. }}
  170. genBlocks := 10
  171. signer := types.HomesteadSigner{}
  172. api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
  173. // Transfer from account[0] to account[1]
  174. // value: 1000 wei
  175. // fee: 0 wei
  176. tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
  177. b.AddTx(tx)
  178. }))
  179. var testSuite = []struct {
  180. blockNumber rpc.BlockNumber
  181. call ethapi.TransactionArgs
  182. config *TraceCallConfig
  183. expectErr error
  184. expect string
  185. }{
  186. // Standard JSON trace upon the genesis, plain transfer.
  187. {
  188. blockNumber: rpc.BlockNumber(0),
  189. call: ethapi.TransactionArgs{
  190. From: &accounts[0].addr,
  191. To: &accounts[1].addr,
  192. Value: (*hexutil.Big)(big.NewInt(1000)),
  193. },
  194. config: nil,
  195. expectErr: nil,
  196. expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
  197. },
  198. // Standard JSON trace upon the head, plain transfer.
  199. {
  200. blockNumber: rpc.BlockNumber(genBlocks),
  201. call: ethapi.TransactionArgs{
  202. From: &accounts[0].addr,
  203. To: &accounts[1].addr,
  204. Value: (*hexutil.Big)(big.NewInt(1000)),
  205. },
  206. config: nil,
  207. expectErr: nil,
  208. expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
  209. },
  210. // Standard JSON trace upon the non-existent block, error expects
  211. {
  212. blockNumber: rpc.BlockNumber(genBlocks + 1),
  213. call: ethapi.TransactionArgs{
  214. From: &accounts[0].addr,
  215. To: &accounts[1].addr,
  216. Value: (*hexutil.Big)(big.NewInt(1000)),
  217. },
  218. config: nil,
  219. expectErr: fmt.Errorf("block #%d not found", genBlocks+1),
  220. //expect: nil,
  221. },
  222. // Standard JSON trace upon the latest block
  223. {
  224. blockNumber: rpc.LatestBlockNumber,
  225. call: ethapi.TransactionArgs{
  226. From: &accounts[0].addr,
  227. To: &accounts[1].addr,
  228. Value: (*hexutil.Big)(big.NewInt(1000)),
  229. },
  230. config: nil,
  231. expectErr: nil,
  232. expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
  233. },
  234. // Tracing on 'pending' should fail:
  235. {
  236. blockNumber: rpc.PendingBlockNumber,
  237. call: ethapi.TransactionArgs{
  238. From: &accounts[0].addr,
  239. To: &accounts[1].addr,
  240. Value: (*hexutil.Big)(big.NewInt(1000)),
  241. },
  242. config: nil,
  243. expectErr: errors.New("tracing on top of pending is not supported"),
  244. },
  245. {
  246. blockNumber: rpc.LatestBlockNumber,
  247. call: ethapi.TransactionArgs{
  248. From: &accounts[0].addr,
  249. Input: &hexutil.Bytes{0x43}, // blocknumber
  250. },
  251. config: &TraceCallConfig{
  252. BlockOverrides: &ethapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
  253. },
  254. expectErr: nil,
  255. expect: ` {"gas":53018,"failed":false,"returnValue":"","structLogs":[
  256. {"pc":0,"op":"NUMBER","gas":24946984,"gasCost":2,"depth":1,"stack":[]},
  257. {"pc":1,"op":"STOP","gas":24946982,"gasCost":0,"depth":1,"stack":["0x1337"]}]}`,
  258. },
  259. }
  260. for i, testspec := range testSuite {
  261. result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config)
  262. if testspec.expectErr != nil {
  263. if err == nil {
  264. t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr)
  265. continue
  266. }
  267. if !reflect.DeepEqual(err, testspec.expectErr) {
  268. t.Errorf("test %d: error mismatch, want %v, git %v", i, testspec.expectErr, err)
  269. }
  270. } else {
  271. if err != nil {
  272. t.Errorf("test %d: expect no error, got %v", i, err)
  273. continue
  274. }
  275. var have *logger.ExecutionResult
  276. if err := json.Unmarshal(result.(json.RawMessage), &have); err != nil {
  277. t.Errorf("test %d: failed to unmarshal result %v", i, err)
  278. }
  279. var want *logger.ExecutionResult
  280. if err := json.Unmarshal([]byte(testspec.expect), &want); err != nil {
  281. t.Errorf("test %d: failed to unmarshal result %v", i, err)
  282. }
  283. if !reflect.DeepEqual(have, want) {
  284. t.Errorf("test %d: result mismatch, want %v, got %v", i, testspec.expect, string(result.(json.RawMessage)))
  285. }
  286. }
  287. }
  288. }
  289. func TestTraceTransaction(t *testing.T) {
  290. t.Parallel()
  291. // Initialize test accounts
  292. accounts := newAccounts(2)
  293. genesis := &core.Genesis{Alloc: core.GenesisAlloc{
  294. accounts[0].addr: {Balance: big.NewInt(params.Ether)},
  295. accounts[1].addr: {Balance: big.NewInt(params.Ether)},
  296. }}
  297. target := common.Hash{}
  298. signer := types.HomesteadSigner{}
  299. api := NewAPI(newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) {
  300. // Transfer from account[0] to account[1]
  301. // value: 1000 wei
  302. // fee: 0 wei
  303. tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
  304. b.AddTx(tx)
  305. target = tx.Hash()
  306. }))
  307. result, err := api.TraceTransaction(context.Background(), target, nil)
  308. if err != nil {
  309. t.Errorf("Failed to trace transaction %v", err)
  310. }
  311. var have *logger.ExecutionResult
  312. if err := json.Unmarshal(result.(json.RawMessage), &have); err != nil {
  313. t.Errorf("failed to unmarshal result %v", err)
  314. }
  315. if !reflect.DeepEqual(have, &logger.ExecutionResult{
  316. Gas: params.TxGas,
  317. Failed: false,
  318. ReturnValue: "",
  319. StructLogs: []logger.StructLogRes{},
  320. }) {
  321. t.Error("Transaction tracing result is different")
  322. }
  323. }
  324. func TestTraceBlock(t *testing.T) {
  325. t.Parallel()
  326. // Initialize test accounts
  327. accounts := newAccounts(3)
  328. genesis := &core.Genesis{Alloc: core.GenesisAlloc{
  329. accounts[0].addr: {Balance: big.NewInt(params.Ether)},
  330. accounts[1].addr: {Balance: big.NewInt(params.Ether)},
  331. accounts[2].addr: {Balance: big.NewInt(params.Ether)},
  332. }}
  333. genBlocks := 10
  334. signer := types.HomesteadSigner{}
  335. api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
  336. // Transfer from account[0] to account[1]
  337. // value: 1000 wei
  338. // fee: 0 wei
  339. tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
  340. b.AddTx(tx)
  341. }))
  342. var testSuite = []struct {
  343. blockNumber rpc.BlockNumber
  344. config *TraceConfig
  345. want string
  346. expectErr error
  347. }{
  348. // Trace genesis block, expect error
  349. {
  350. blockNumber: rpc.BlockNumber(0),
  351. expectErr: errors.New("genesis is not traceable"),
  352. },
  353. // Trace head block
  354. {
  355. blockNumber: rpc.BlockNumber(genBlocks),
  356. want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
  357. },
  358. // Trace non-existent block
  359. {
  360. blockNumber: rpc.BlockNumber(genBlocks + 1),
  361. expectErr: fmt.Errorf("block #%d not found", genBlocks+1),
  362. },
  363. // Trace latest block
  364. {
  365. blockNumber: rpc.LatestBlockNumber,
  366. want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
  367. },
  368. // Trace pending block
  369. {
  370. blockNumber: rpc.PendingBlockNumber,
  371. want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
  372. },
  373. }
  374. for i, tc := range testSuite {
  375. result, err := api.TraceBlockByNumber(context.Background(), tc.blockNumber, tc.config)
  376. if tc.expectErr != nil {
  377. if err == nil {
  378. t.Errorf("test %d, want error %v", i, tc.expectErr)
  379. continue
  380. }
  381. if !reflect.DeepEqual(err, tc.expectErr) {
  382. t.Errorf("test %d: error mismatch, want %v, get %v", i, tc.expectErr, err)
  383. }
  384. continue
  385. }
  386. if err != nil {
  387. t.Errorf("test %d, want no error, have %v", i, err)
  388. continue
  389. }
  390. have, _ := json.Marshal(result)
  391. want := tc.want
  392. if string(have) != want {
  393. t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(have), want)
  394. }
  395. }
  396. }
  397. func TestTracingWithOverrides(t *testing.T) {
  398. t.Parallel()
  399. // Initialize test accounts
  400. accounts := newAccounts(3)
  401. genesis := &core.Genesis{Alloc: core.GenesisAlloc{
  402. accounts[0].addr: {Balance: big.NewInt(params.Ether)},
  403. accounts[1].addr: {Balance: big.NewInt(params.Ether)},
  404. accounts[2].addr: {Balance: big.NewInt(params.Ether)},
  405. }}
  406. genBlocks := 10
  407. signer := types.HomesteadSigner{}
  408. api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
  409. // Transfer from account[0] to account[1]
  410. // value: 1000 wei
  411. // fee: 0 wei
  412. tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
  413. b.AddTx(tx)
  414. }))
  415. randomAccounts := newAccounts(3)
  416. type res struct {
  417. Gas int
  418. Failed bool
  419. ReturnValue string
  420. }
  421. var testSuite = []struct {
  422. blockNumber rpc.BlockNumber
  423. call ethapi.TransactionArgs
  424. config *TraceCallConfig
  425. expectErr error
  426. want string
  427. }{
  428. // Call which can only succeed if state is state overridden
  429. {
  430. blockNumber: rpc.LatestBlockNumber,
  431. call: ethapi.TransactionArgs{
  432. From: &randomAccounts[0].addr,
  433. To: &randomAccounts[1].addr,
  434. Value: (*hexutil.Big)(big.NewInt(1000)),
  435. },
  436. config: &TraceCallConfig{
  437. StateOverrides: &ethapi.StateOverride{
  438. randomAccounts[0].addr: ethapi.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))},
  439. },
  440. },
  441. want: `{"gas":21000,"failed":false,"returnValue":""}`,
  442. },
  443. // Invalid call without state overriding
  444. {
  445. blockNumber: rpc.LatestBlockNumber,
  446. call: ethapi.TransactionArgs{
  447. From: &randomAccounts[0].addr,
  448. To: &randomAccounts[1].addr,
  449. Value: (*hexutil.Big)(big.NewInt(1000)),
  450. },
  451. config: &TraceCallConfig{},
  452. expectErr: core.ErrInsufficientFunds,
  453. },
  454. // Successful simple contract call
  455. //
  456. // // SPDX-License-Identifier: GPL-3.0
  457. //
  458. // pragma solidity >=0.7.0 <0.8.0;
  459. //
  460. // /**
  461. // * @title Storage
  462. // * @dev Store & retrieve value in a variable
  463. // */
  464. // contract Storage {
  465. // uint256 public number;
  466. // constructor() {
  467. // number = block.number;
  468. // }
  469. // }
  470. {
  471. blockNumber: rpc.LatestBlockNumber,
  472. call: ethapi.TransactionArgs{
  473. From: &randomAccounts[0].addr,
  474. To: &randomAccounts[2].addr,
  475. Data: newRPCBytes(common.Hex2Bytes("8381f58a")), // call number()
  476. },
  477. config: &TraceCallConfig{
  478. //Tracer: &tracer,
  479. StateOverrides: &ethapi.StateOverride{
  480. randomAccounts[2].addr: ethapi.OverrideAccount{
  481. Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")),
  482. StateDiff: newStates([]common.Hash{{}}, []common.Hash{common.BigToHash(big.NewInt(123))}),
  483. },
  484. },
  485. },
  486. want: `{"gas":23347,"failed":false,"returnValue":"000000000000000000000000000000000000000000000000000000000000007b"}`,
  487. },
  488. { // Override blocknumber
  489. blockNumber: rpc.LatestBlockNumber,
  490. call: ethapi.TransactionArgs{
  491. From: &accounts[0].addr,
  492. // BLOCKNUMBER PUSH1 MSTORE
  493. Input: newRPCBytes(common.Hex2Bytes("4360005260206000f3")),
  494. //&hexutil.Bytes{0x43}, // blocknumber
  495. },
  496. config: &TraceCallConfig{
  497. BlockOverrides: &ethapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
  498. },
  499. want: `{"gas":59537,"failed":false,"returnValue":"0000000000000000000000000000000000000000000000000000000000001337"}`,
  500. },
  501. { // Override blocknumber, and query a blockhash
  502. blockNumber: rpc.LatestBlockNumber,
  503. call: ethapi.TransactionArgs{
  504. From: &accounts[0].addr,
  505. Input: &hexutil.Bytes{
  506. 0x60, 0x00, 0x40, // BLOCKHASH(0)
  507. 0x60, 0x00, 0x52, // STORE memory offset 0
  508. 0x61, 0x13, 0x36, 0x40, // BLOCKHASH(0x1336)
  509. 0x60, 0x20, 0x52, // STORE memory offset 32
  510. 0x61, 0x13, 0x37, 0x40, // BLOCKHASH(0x1337)
  511. 0x60, 0x40, 0x52, // STORE memory offset 64
  512. 0x60, 0x60, 0x60, 0x00, 0xf3, // RETURN (0-96)
  513. }, // blocknumber
  514. },
  515. config: &TraceCallConfig{
  516. BlockOverrides: &ethapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
  517. },
  518. want: `{"gas":72666,"failed":false,"returnValue":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}`,
  519. },
  520. }
  521. for i, tc := range testSuite {
  522. result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config)
  523. if tc.expectErr != nil {
  524. if err == nil {
  525. t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr)
  526. continue
  527. }
  528. if !errors.Is(err, tc.expectErr) {
  529. t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err)
  530. }
  531. continue
  532. }
  533. if err != nil {
  534. t.Errorf("test %d: want no error, have %v", i, err)
  535. continue
  536. }
  537. // Turn result into res-struct
  538. var (
  539. have res
  540. want res
  541. )
  542. resBytes, _ := json.Marshal(result)
  543. json.Unmarshal(resBytes, &have)
  544. json.Unmarshal([]byte(tc.want), &want)
  545. if !reflect.DeepEqual(have, want) {
  546. t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(resBytes), want)
  547. }
  548. }
  549. }
  550. type Account struct {
  551. key *ecdsa.PrivateKey
  552. addr common.Address
  553. }
  554. type Accounts []Account
  555. func (a Accounts) Len() int { return len(a) }
  556. func (a Accounts) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  557. func (a Accounts) Less(i, j int) bool { return bytes.Compare(a[i].addr.Bytes(), a[j].addr.Bytes()) < 0 }
  558. func newAccounts(n int) (accounts Accounts) {
  559. for i := 0; i < n; i++ {
  560. key, _ := crypto.GenerateKey()
  561. addr := crypto.PubkeyToAddress(key.PublicKey)
  562. accounts = append(accounts, Account{key: key, addr: addr})
  563. }
  564. sort.Sort(accounts)
  565. return accounts
  566. }
  567. func newRPCBalance(balance *big.Int) **hexutil.Big {
  568. rpcBalance := (*hexutil.Big)(balance)
  569. return &rpcBalance
  570. }
  571. func newRPCBytes(bytes []byte) *hexutil.Bytes {
  572. rpcBytes := hexutil.Bytes(bytes)
  573. return &rpcBytes
  574. }
  575. func newStates(keys []common.Hash, vals []common.Hash) *map[common.Hash]common.Hash {
  576. if len(keys) != len(vals) {
  577. panic("invalid input")
  578. }
  579. m := make(map[common.Hash]common.Hash)
  580. for i := 0; i < len(keys); i++ {
  581. m[keys[i]] = vals[i]
  582. }
  583. return &m
  584. }