api_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  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. "errors"
  22. "fmt"
  23. "math/big"
  24. "reflect"
  25. "sort"
  26. "testing"
  27. "time"
  28. "github.com/ethereum/go-ethereum/common"
  29. "github.com/ethereum/go-ethereum/common/hexutil"
  30. "github.com/ethereum/go-ethereum/consensus"
  31. "github.com/ethereum/go-ethereum/consensus/ethash"
  32. "github.com/ethereum/go-ethereum/core"
  33. "github.com/ethereum/go-ethereum/core/rawdb"
  34. "github.com/ethereum/go-ethereum/core/state"
  35. "github.com/ethereum/go-ethereum/core/types"
  36. "github.com/ethereum/go-ethereum/core/vm"
  37. "github.com/ethereum/go-ethereum/crypto"
  38. "github.com/ethereum/go-ethereum/ethdb"
  39. "github.com/ethereum/go-ethereum/internal/ethapi"
  40. "github.com/ethereum/go-ethereum/params"
  41. "github.com/ethereum/go-ethereum/rpc"
  42. )
  43. var (
  44. errStateNotFound = errors.New("state not found")
  45. errBlockNotFound = errors.New("block not found")
  46. errTransactionNotFound = errors.New("transaction not found")
  47. )
  48. type testBackend struct {
  49. chainConfig *params.ChainConfig
  50. engine consensus.Engine
  51. chaindb ethdb.Database
  52. chain *core.BlockChain
  53. }
  54. func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend {
  55. backend := &testBackend{
  56. chainConfig: params.TestChainConfig,
  57. engine: ethash.NewFaker(),
  58. chaindb: rawdb.NewMemoryDatabase(),
  59. }
  60. // Generate blocks for testing
  61. gspec.Config = backend.chainConfig
  62. var (
  63. gendb = rawdb.NewMemoryDatabase()
  64. genesis = gspec.MustCommit(gendb)
  65. )
  66. blocks, _ := core.GenerateChain(backend.chainConfig, genesis, backend.engine, gendb, n, generator)
  67. // Import the canonical chain
  68. gspec.MustCommit(backend.chaindb)
  69. cacheConfig := &core.CacheConfig{
  70. TrieCleanLimit: 256,
  71. TrieDirtyLimit: 256,
  72. TrieTimeLimit: 5 * time.Minute,
  73. SnapshotLimit: 0,
  74. TrieDirtyDisabled: true, // Archive mode
  75. }
  76. chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, backend.chainConfig, backend.engine, vm.Config{}, nil, nil)
  77. if err != nil {
  78. t.Fatalf("failed to create tester chain: %v", err)
  79. }
  80. if n, err := chain.InsertChain(blocks); err != nil {
  81. t.Fatalf("block %d: failed to insert into chain: %v", n, err)
  82. }
  83. backend.chain = chain
  84. return backend
  85. }
  86. func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
  87. return b.chain.GetHeaderByHash(hash), nil
  88. }
  89. func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
  90. if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber {
  91. return b.chain.CurrentHeader(), nil
  92. }
  93. return b.chain.GetHeaderByNumber(uint64(number)), nil
  94. }
  95. func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
  96. return b.chain.GetBlockByHash(hash), nil
  97. }
  98. func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
  99. if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber {
  100. return b.chain.CurrentBlock(), nil
  101. }
  102. return b.chain.GetBlockByNumber(uint64(number)), nil
  103. }
  104. func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
  105. tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash)
  106. if tx == nil {
  107. return nil, common.Hash{}, 0, 0, errTransactionNotFound
  108. }
  109. return tx, hash, blockNumber, index, nil
  110. }
  111. func (b *testBackend) RPCGasCap() uint64 {
  112. return 25000000
  113. }
  114. func (b *testBackend) ChainConfig() *params.ChainConfig {
  115. return b.chainConfig
  116. }
  117. func (b *testBackend) Engine() consensus.Engine {
  118. return b.engine
  119. }
  120. func (b *testBackend) ChainDb() ethdb.Database {
  121. return b.chaindb
  122. }
  123. func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (*state.StateDB, error) {
  124. statedb, err := b.chain.StateAt(block.Root())
  125. if err != nil {
  126. return nil, errStateNotFound
  127. }
  128. return statedb, nil
  129. }
  130. func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) {
  131. parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1)
  132. if parent == nil {
  133. return nil, vm.BlockContext{}, nil, errBlockNotFound
  134. }
  135. statedb, err := b.chain.StateAt(parent.Root())
  136. if err != nil {
  137. return nil, vm.BlockContext{}, nil, errStateNotFound
  138. }
  139. if txIndex == 0 && len(block.Transactions()) == 0 {
  140. return nil, vm.BlockContext{}, statedb, nil
  141. }
  142. // Recompute transactions up to the target index.
  143. signer := types.MakeSigner(b.chainConfig, block.Number())
  144. for idx, tx := range block.Transactions() {
  145. msg, _ := tx.AsMessage(signer)
  146. txContext := core.NewEVMTxContext(msg)
  147. context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
  148. if idx == txIndex {
  149. return msg, context, statedb, nil
  150. }
  151. vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{})
  152. if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
  153. return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
  154. }
  155. statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
  156. }
  157. return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
  158. }
  159. func TestTraceCall(t *testing.T) {
  160. t.Parallel()
  161. // Initialize test accounts
  162. accounts := newAccounts(3)
  163. genesis := &core.Genesis{Alloc: core.GenesisAlloc{
  164. accounts[0].addr: {Balance: big.NewInt(params.Ether)},
  165. accounts[1].addr: {Balance: big.NewInt(params.Ether)},
  166. accounts[2].addr: {Balance: big.NewInt(params.Ether)},
  167. }}
  168. genBlocks := 10
  169. signer := types.HomesteadSigner{}
  170. api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
  171. // Transfer from account[0] to account[1]
  172. // value: 1000 wei
  173. // fee: 0 wei
  174. tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, big.NewInt(0), nil), signer, accounts[0].key)
  175. b.AddTx(tx)
  176. }))
  177. var testSuite = []struct {
  178. blockNumber rpc.BlockNumber
  179. call ethapi.CallArgs
  180. config *TraceConfig
  181. expectErr error
  182. expect interface{}
  183. }{
  184. // Standard JSON trace upon the genesis, plain transfer.
  185. {
  186. blockNumber: rpc.BlockNumber(0),
  187. call: ethapi.CallArgs{
  188. From: &accounts[0].addr,
  189. To: &accounts[1].addr,
  190. Value: (*hexutil.Big)(big.NewInt(1000)),
  191. },
  192. config: nil,
  193. expectErr: nil,
  194. expect: &ethapi.ExecutionResult{
  195. Gas: params.TxGas,
  196. Failed: false,
  197. ReturnValue: "",
  198. StructLogs: []ethapi.StructLogRes{},
  199. },
  200. },
  201. // Standard JSON trace upon the head, plain transfer.
  202. {
  203. blockNumber: rpc.BlockNumber(genBlocks),
  204. call: ethapi.CallArgs{
  205. From: &accounts[0].addr,
  206. To: &accounts[1].addr,
  207. Value: (*hexutil.Big)(big.NewInt(1000)),
  208. },
  209. config: nil,
  210. expectErr: nil,
  211. expect: &ethapi.ExecutionResult{
  212. Gas: params.TxGas,
  213. Failed: false,
  214. ReturnValue: "",
  215. StructLogs: []ethapi.StructLogRes{},
  216. },
  217. },
  218. // Standard JSON trace upon the non-existent block, error expects
  219. {
  220. blockNumber: rpc.BlockNumber(genBlocks + 1),
  221. call: ethapi.CallArgs{
  222. From: &accounts[0].addr,
  223. To: &accounts[1].addr,
  224. Value: (*hexutil.Big)(big.NewInt(1000)),
  225. },
  226. config: nil,
  227. expectErr: fmt.Errorf("block #%d not found", genBlocks+1),
  228. expect: nil,
  229. },
  230. // Standard JSON trace upon the latest block
  231. {
  232. blockNumber: rpc.LatestBlockNumber,
  233. call: ethapi.CallArgs{
  234. From: &accounts[0].addr,
  235. To: &accounts[1].addr,
  236. Value: (*hexutil.Big)(big.NewInt(1000)),
  237. },
  238. config: nil,
  239. expectErr: nil,
  240. expect: &ethapi.ExecutionResult{
  241. Gas: params.TxGas,
  242. Failed: false,
  243. ReturnValue: "",
  244. StructLogs: []ethapi.StructLogRes{},
  245. },
  246. },
  247. // Standard JSON trace upon the pending block
  248. {
  249. blockNumber: rpc.PendingBlockNumber,
  250. call: ethapi.CallArgs{
  251. From: &accounts[0].addr,
  252. To: &accounts[1].addr,
  253. Value: (*hexutil.Big)(big.NewInt(1000)),
  254. },
  255. config: nil,
  256. expectErr: nil,
  257. expect: &ethapi.ExecutionResult{
  258. Gas: params.TxGas,
  259. Failed: false,
  260. ReturnValue: "",
  261. StructLogs: []ethapi.StructLogRes{},
  262. },
  263. },
  264. }
  265. for _, testspec := range testSuite {
  266. result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config)
  267. if testspec.expectErr != nil {
  268. if err == nil {
  269. t.Errorf("Expect error %v, get nothing", testspec.expectErr)
  270. continue
  271. }
  272. if !reflect.DeepEqual(err, testspec.expectErr) {
  273. t.Errorf("Error mismatch, want %v, get %v", testspec.expectErr, err)
  274. }
  275. } else {
  276. if err != nil {
  277. t.Errorf("Expect no error, get %v", err)
  278. continue
  279. }
  280. if !reflect.DeepEqual(result, testspec.expect) {
  281. t.Errorf("Result mismatch, want %v, get %v", testspec.expect, result)
  282. }
  283. }
  284. }
  285. }
  286. func TestTraceTransaction(t *testing.T) {
  287. t.Parallel()
  288. // Initialize test accounts
  289. accounts := newAccounts(2)
  290. genesis := &core.Genesis{Alloc: core.GenesisAlloc{
  291. accounts[0].addr: {Balance: big.NewInt(params.Ether)},
  292. accounts[1].addr: {Balance: big.NewInt(params.Ether)},
  293. }}
  294. target := common.Hash{}
  295. signer := types.HomesteadSigner{}
  296. api := NewAPI(newTestBackend(t, 1, genesis, func(i int, b *core.BlockGen) {
  297. // Transfer from account[0] to account[1]
  298. // value: 1000 wei
  299. // fee: 0 wei
  300. tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, big.NewInt(0), nil), signer, accounts[0].key)
  301. b.AddTx(tx)
  302. target = tx.Hash()
  303. }))
  304. result, err := api.TraceTransaction(context.Background(), target, nil)
  305. if err != nil {
  306. t.Errorf("Failed to trace transaction %v", err)
  307. }
  308. if !reflect.DeepEqual(result, &ethapi.ExecutionResult{
  309. Gas: params.TxGas,
  310. Failed: false,
  311. ReturnValue: "",
  312. StructLogs: []ethapi.StructLogRes{},
  313. }) {
  314. t.Error("Transaction tracing result is different")
  315. }
  316. }
  317. func TestTraceBlock(t *testing.T) {
  318. t.Parallel()
  319. // Initialize test accounts
  320. accounts := newAccounts(3)
  321. genesis := &core.Genesis{Alloc: core.GenesisAlloc{
  322. accounts[0].addr: {Balance: big.NewInt(params.Ether)},
  323. accounts[1].addr: {Balance: big.NewInt(params.Ether)},
  324. accounts[2].addr: {Balance: big.NewInt(params.Ether)},
  325. }}
  326. genBlocks := 10
  327. signer := types.HomesteadSigner{}
  328. api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
  329. // Transfer from account[0] to account[1]
  330. // value: 1000 wei
  331. // fee: 0 wei
  332. tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, big.NewInt(0), nil), signer, accounts[0].key)
  333. b.AddTx(tx)
  334. }))
  335. var testSuite = []struct {
  336. blockNumber rpc.BlockNumber
  337. config *TraceConfig
  338. expect interface{}
  339. expectErr error
  340. }{
  341. // Trace genesis block, expect error
  342. {
  343. blockNumber: rpc.BlockNumber(0),
  344. config: nil,
  345. expect: nil,
  346. expectErr: errors.New("genesis is not traceable"),
  347. },
  348. // Trace head block
  349. {
  350. blockNumber: rpc.BlockNumber(genBlocks),
  351. config: nil,
  352. expectErr: nil,
  353. expect: []*txTraceResult{
  354. {
  355. Result: &ethapi.ExecutionResult{
  356. Gas: params.TxGas,
  357. Failed: false,
  358. ReturnValue: "",
  359. StructLogs: []ethapi.StructLogRes{},
  360. },
  361. },
  362. },
  363. },
  364. // Trace non-existent block
  365. {
  366. blockNumber: rpc.BlockNumber(genBlocks + 1),
  367. config: nil,
  368. expectErr: fmt.Errorf("block #%d not found", genBlocks+1),
  369. expect: nil,
  370. },
  371. // Trace latest block
  372. {
  373. blockNumber: rpc.LatestBlockNumber,
  374. config: nil,
  375. expectErr: nil,
  376. expect: []*txTraceResult{
  377. {
  378. Result: &ethapi.ExecutionResult{
  379. Gas: params.TxGas,
  380. Failed: false,
  381. ReturnValue: "",
  382. StructLogs: []ethapi.StructLogRes{},
  383. },
  384. },
  385. },
  386. },
  387. // Trace pending block
  388. {
  389. blockNumber: rpc.PendingBlockNumber,
  390. config: nil,
  391. expectErr: nil,
  392. expect: []*txTraceResult{
  393. {
  394. Result: &ethapi.ExecutionResult{
  395. Gas: params.TxGas,
  396. Failed: false,
  397. ReturnValue: "",
  398. StructLogs: []ethapi.StructLogRes{},
  399. },
  400. },
  401. },
  402. },
  403. }
  404. for _, testspec := range testSuite {
  405. result, err := api.TraceBlockByNumber(context.Background(), testspec.blockNumber, testspec.config)
  406. if testspec.expectErr != nil {
  407. if err == nil {
  408. t.Errorf("Expect error %v, get nothing", testspec.expectErr)
  409. continue
  410. }
  411. if !reflect.DeepEqual(err, testspec.expectErr) {
  412. t.Errorf("Error mismatch, want %v, get %v", testspec.expectErr, err)
  413. }
  414. } else {
  415. if err != nil {
  416. t.Errorf("Expect no error, get %v", err)
  417. continue
  418. }
  419. if !reflect.DeepEqual(result, testspec.expect) {
  420. t.Errorf("Result mismatch, want %v, get %v", testspec.expect, result)
  421. }
  422. }
  423. }
  424. }
  425. type Account struct {
  426. key *ecdsa.PrivateKey
  427. addr common.Address
  428. }
  429. type Accounts []Account
  430. func (a Accounts) Len() int { return len(a) }
  431. func (a Accounts) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  432. func (a Accounts) Less(i, j int) bool { return bytes.Compare(a[i].addr.Bytes(), a[j].addr.Bytes()) < 0 }
  433. func newAccounts(n int) (accounts Accounts) {
  434. for i := 0; i < n; i++ {
  435. key, _ := crypto.GenerateKey()
  436. addr := crypto.PubkeyToAddress(key.PublicKey)
  437. accounts = append(accounts, Account{key: key, addr: addr})
  438. }
  439. sort.Sort(accounts)
  440. return accounts
  441. }