ethclient_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. // Copyright 2016 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 ethclient
  17. import (
  18. "context"
  19. "errors"
  20. "fmt"
  21. "math/big"
  22. "reflect"
  23. "testing"
  24. "time"
  25. "github.com/ethereum/go-ethereum"
  26. "github.com/ethereum/go-ethereum/common"
  27. "github.com/ethereum/go-ethereum/consensus/ethash"
  28. "github.com/ethereum/go-ethereum/core"
  29. "github.com/ethereum/go-ethereum/core/rawdb"
  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/eth"
  34. "github.com/ethereum/go-ethereum/eth/ethconfig"
  35. "github.com/ethereum/go-ethereum/ethdb/memorydb"
  36. "github.com/ethereum/go-ethereum/node"
  37. "github.com/ethereum/go-ethereum/params"
  38. "github.com/ethereum/go-ethereum/rpc"
  39. )
  40. // Verify that Client implements the ethereum interfaces.
  41. var (
  42. _ = ethereum.ChainReader(&Client{})
  43. _ = ethereum.TransactionReader(&Client{})
  44. _ = ethereum.ChainStateReader(&Client{})
  45. _ = ethereum.ChainSyncReader(&Client{})
  46. _ = ethereum.ContractCaller(&Client{})
  47. _ = ethereum.GasEstimator(&Client{})
  48. _ = ethereum.GasPricer(&Client{})
  49. _ = ethereum.LogFilterer(&Client{})
  50. _ = ethereum.PendingStateReader(&Client{})
  51. // _ = ethereum.PendingStateEventer(&Client{})
  52. _ = ethereum.PendingContractCaller(&Client{})
  53. )
  54. func TestToFilterArg(t *testing.T) {
  55. blockHashErr := fmt.Errorf("cannot specify both BlockHash and FromBlock/ToBlock")
  56. addresses := []common.Address{
  57. common.HexToAddress("0xD36722ADeC3EdCB29c8e7b5a47f352D701393462"),
  58. }
  59. blockHash := common.HexToHash(
  60. "0xeb94bb7d78b73657a9d7a99792413f50c0a45c51fc62bdcb08a53f18e9a2b4eb",
  61. )
  62. for _, testCase := range []struct {
  63. name string
  64. input ethereum.FilterQuery
  65. output interface{}
  66. err error
  67. }{
  68. {
  69. "without BlockHash",
  70. ethereum.FilterQuery{
  71. Addresses: addresses,
  72. FromBlock: big.NewInt(1),
  73. ToBlock: big.NewInt(2),
  74. Topics: [][]common.Hash{},
  75. },
  76. map[string]interface{}{
  77. "address": addresses,
  78. "fromBlock": "0x1",
  79. "toBlock": "0x2",
  80. "topics": [][]common.Hash{},
  81. },
  82. nil,
  83. },
  84. {
  85. "with nil fromBlock and nil toBlock",
  86. ethereum.FilterQuery{
  87. Addresses: addresses,
  88. Topics: [][]common.Hash{},
  89. },
  90. map[string]interface{}{
  91. "address": addresses,
  92. "fromBlock": "0x0",
  93. "toBlock": "latest",
  94. "topics": [][]common.Hash{},
  95. },
  96. nil,
  97. },
  98. {
  99. "with negative fromBlock and negative toBlock",
  100. ethereum.FilterQuery{
  101. Addresses: addresses,
  102. FromBlock: big.NewInt(-1),
  103. ToBlock: big.NewInt(-1),
  104. Topics: [][]common.Hash{},
  105. },
  106. map[string]interface{}{
  107. "address": addresses,
  108. "fromBlock": "pending",
  109. "toBlock": "pending",
  110. "topics": [][]common.Hash{},
  111. },
  112. nil,
  113. },
  114. {
  115. "with blockhash",
  116. ethereum.FilterQuery{
  117. Addresses: addresses,
  118. BlockHash: &blockHash,
  119. Topics: [][]common.Hash{},
  120. },
  121. map[string]interface{}{
  122. "address": addresses,
  123. "blockHash": blockHash,
  124. "topics": [][]common.Hash{},
  125. },
  126. nil,
  127. },
  128. {
  129. "with blockhash and from block",
  130. ethereum.FilterQuery{
  131. Addresses: addresses,
  132. BlockHash: &blockHash,
  133. FromBlock: big.NewInt(1),
  134. Topics: [][]common.Hash{},
  135. },
  136. nil,
  137. blockHashErr,
  138. },
  139. {
  140. "with blockhash and to block",
  141. ethereum.FilterQuery{
  142. Addresses: addresses,
  143. BlockHash: &blockHash,
  144. ToBlock: big.NewInt(1),
  145. Topics: [][]common.Hash{},
  146. },
  147. nil,
  148. blockHashErr,
  149. },
  150. {
  151. "with blockhash and both from / to block",
  152. ethereum.FilterQuery{
  153. Addresses: addresses,
  154. BlockHash: &blockHash,
  155. FromBlock: big.NewInt(1),
  156. ToBlock: big.NewInt(2),
  157. Topics: [][]common.Hash{},
  158. },
  159. nil,
  160. blockHashErr,
  161. },
  162. } {
  163. t.Run(testCase.name, func(t *testing.T) {
  164. output, err := toFilterArg(testCase.input)
  165. if (testCase.err == nil) != (err == nil) {
  166. t.Fatalf("expected error %v but got %v", testCase.err, err)
  167. }
  168. if testCase.err != nil {
  169. if testCase.err.Error() != err.Error() {
  170. t.Fatalf("expected error %v but got %v", testCase.err, err)
  171. }
  172. } else if !reflect.DeepEqual(testCase.output, output) {
  173. t.Fatalf("expected filter arg %v but got %v", testCase.output, output)
  174. }
  175. })
  176. }
  177. }
  178. var (
  179. testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  180. testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
  181. testBalance = big.NewInt(2e10)
  182. testBlockNum = 128
  183. testBlocks = []testBlockParam{
  184. {
  185. // This txs params also used to default block.
  186. blockNr: 10,
  187. txs: []testTransactionParam{},
  188. },
  189. {
  190. blockNr: 11,
  191. txs: []testTransactionParam{
  192. {
  193. to: common.Address{0x01},
  194. value: big.NewInt(1),
  195. gasPrice: big.NewInt(1),
  196. data: nil,
  197. },
  198. },
  199. },
  200. {
  201. blockNr: 12,
  202. txs: []testTransactionParam{
  203. {
  204. to: common.Address{0x01},
  205. value: big.NewInt(1),
  206. gasPrice: big.NewInt(1),
  207. data: nil,
  208. },
  209. {
  210. to: common.Address{0x02},
  211. value: big.NewInt(2),
  212. gasPrice: big.NewInt(2),
  213. data: nil,
  214. },
  215. },
  216. },
  217. {
  218. blockNr: 13,
  219. txs: []testTransactionParam{
  220. {
  221. to: common.Address{0x01},
  222. value: big.NewInt(1),
  223. gasPrice: big.NewInt(1),
  224. data: nil,
  225. },
  226. {
  227. to: common.Address{0x02},
  228. value: big.NewInt(2),
  229. gasPrice: big.NewInt(2),
  230. data: nil,
  231. },
  232. {
  233. to: common.Address{0x03},
  234. value: big.NewInt(3),
  235. gasPrice: big.NewInt(3),
  236. data: nil,
  237. },
  238. },
  239. },
  240. }
  241. )
  242. type testTransactionParam struct {
  243. to common.Address
  244. value *big.Int
  245. gasPrice *big.Int
  246. data []byte
  247. }
  248. type testBlockParam struct {
  249. blockNr int
  250. txs []testTransactionParam
  251. }
  252. func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
  253. // Generate test chain.
  254. genesis, blocks := generateTestChain()
  255. // Create node
  256. n, err := node.New(&node.Config{})
  257. if err != nil {
  258. t.Fatalf("can't create new node: %v", err)
  259. }
  260. // Create Ethereum Service
  261. config := &ethconfig.Config{Genesis: genesis}
  262. config.Ethash.PowMode = ethash.ModeFake
  263. config.SnapshotCache = 256
  264. config.TriesInMemory = 128
  265. ethservice, err := eth.New(n, config)
  266. if err != nil {
  267. t.Fatalf("can't create new ethereum service: %v", err)
  268. }
  269. // Import the test chain.
  270. if err := n.Start(); err != nil {
  271. t.Fatalf("can't start test node: %v", err)
  272. }
  273. if _, err := ethservice.BlockChain().InsertChain(blocks[1:]); err != nil {
  274. t.Fatalf("can't import test blocks: %v", err)
  275. }
  276. return n, blocks
  277. }
  278. func generateTestChain() (*core.Genesis, []*types.Block) {
  279. signer := types.HomesteadSigner{}
  280. // Create a database pre-initialize with a genesis block
  281. db := rawdb.NewMemoryDatabase()
  282. db.SetDiffStore(memorydb.New())
  283. config := params.AllEthashProtocolChanges
  284. genesis := &core.Genesis{
  285. Config: config,
  286. Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance}},
  287. ExtraData: []byte("test genesis"),
  288. Timestamp: 9000,
  289. }
  290. genesis.MustCommit(db)
  291. chain, _ := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, core.EnablePersistDiff(860000))
  292. generate := func(i int, block *core.BlockGen) {
  293. block.OffsetTime(5)
  294. block.SetExtra([]byte("test"))
  295. //block.SetCoinbase(testAddr)
  296. for idx, testBlock := range testBlocks {
  297. // Specific block setting, the index in this generator has 1 diff from specified blockNr.
  298. if i+1 == testBlock.blockNr {
  299. for _, testTransaction := range testBlock.txs {
  300. tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), testTransaction.to,
  301. testTransaction.value, params.TxGas, testTransaction.gasPrice, testTransaction.data), signer, testKey)
  302. if err != nil {
  303. panic(err)
  304. }
  305. block.AddTxWithChain(chain, tx)
  306. }
  307. break
  308. }
  309. // Default block setting.
  310. if idx == len(testBlocks)-1 {
  311. // We want to simulate an empty middle block, having the same state as the
  312. // first one. The last is needs a state change again to force a reorg.
  313. for _, testTransaction := range testBlocks[0].txs {
  314. tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddr), testTransaction.to,
  315. testTransaction.value, params.TxGas, testTransaction.gasPrice, testTransaction.data), signer, testKey)
  316. if err != nil {
  317. panic(err)
  318. }
  319. block.AddTxWithChain(chain, tx)
  320. }
  321. }
  322. }
  323. }
  324. gblock := genesis.ToBlock(db)
  325. engine := ethash.NewFaker()
  326. blocks, _ := core.GenerateChain(config, gblock, engine, db, testBlockNum, generate)
  327. blocks = append([]*types.Block{gblock}, blocks...)
  328. return genesis, blocks
  329. }
  330. func TestEthClient(t *testing.T) {
  331. backend, chain := newTestBackend(t)
  332. client, _ := backend.Attach()
  333. defer backend.Close()
  334. defer client.Close()
  335. tests := map[string]struct {
  336. test func(t *testing.T)
  337. }{
  338. "TestHeader": {
  339. func(t *testing.T) { testHeader(t, chain, client) },
  340. },
  341. "TestBalanceAt": {
  342. func(t *testing.T) { testBalanceAt(t, client) },
  343. },
  344. "TestTxInBlockInterrupted": {
  345. func(t *testing.T) { testTransactionInBlockInterrupted(t, client) },
  346. },
  347. "TestChainID": {
  348. func(t *testing.T) { testChainID(t, client) },
  349. },
  350. "TestGetBlock": {
  351. func(t *testing.T) { testGetBlock(t, client) },
  352. },
  353. "TestStatusFunctions": {
  354. func(t *testing.T) { testStatusFunctions(t, client) },
  355. },
  356. "TestCallContract": {
  357. func(t *testing.T) { testCallContract(t, client) },
  358. },
  359. "TestDiffAccounts": {
  360. func(t *testing.T) { testDiffAccounts(t, client) },
  361. },
  362. // DO not have TestAtFunctions now, because we do not have pending block now
  363. }
  364. t.Parallel()
  365. for name, tt := range tests {
  366. t.Run(name, tt.test)
  367. }
  368. }
  369. func testHeader(t *testing.T, chain []*types.Block, client *rpc.Client) {
  370. tests := map[string]struct {
  371. block *big.Int
  372. want *types.Header
  373. wantErr error
  374. }{
  375. "genesis": {
  376. block: big.NewInt(0),
  377. want: chain[0].Header(),
  378. },
  379. "first_block": {
  380. block: big.NewInt(1),
  381. want: chain[1].Header(),
  382. },
  383. "future_block": {
  384. block: big.NewInt(1000000000),
  385. want: nil,
  386. wantErr: ethereum.NotFound,
  387. },
  388. }
  389. for name, tt := range tests {
  390. t.Run(name, func(t *testing.T) {
  391. ec := NewClient(client)
  392. ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
  393. defer cancel()
  394. got, err := ec.HeaderByNumber(ctx, tt.block)
  395. if !errors.Is(err, tt.wantErr) {
  396. t.Fatalf("HeaderByNumber(%v) error = %q, want %q", tt.block, err, tt.wantErr)
  397. }
  398. if got != nil && got.Number != nil && got.Number.Sign() == 0 {
  399. got.Number = big.NewInt(0) // hack to make DeepEqual work
  400. }
  401. if !reflect.DeepEqual(got, tt.want) {
  402. t.Fatalf("HeaderByNumber(%v)\n = %v\nwant %v", tt.block, got, tt.want)
  403. }
  404. })
  405. }
  406. }
  407. func testBalanceAt(t *testing.T, client *rpc.Client) {
  408. tests := map[string]struct {
  409. account common.Address
  410. block *big.Int
  411. want *big.Int
  412. wantErr error
  413. }{
  414. "valid_account": {
  415. account: testAddr,
  416. block: big.NewInt(1),
  417. want: testBalance,
  418. },
  419. "non_existent_account": {
  420. account: common.Address{1},
  421. block: big.NewInt(1),
  422. want: big.NewInt(0),
  423. },
  424. "future_block": {
  425. account: testAddr,
  426. block: big.NewInt(1000000000),
  427. want: big.NewInt(0),
  428. wantErr: errors.New("header not found"),
  429. },
  430. }
  431. for name, tt := range tests {
  432. t.Run(name, func(t *testing.T) {
  433. ec := NewClient(client)
  434. ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
  435. defer cancel()
  436. got, err := ec.BalanceAt(ctx, tt.account, tt.block)
  437. if tt.wantErr != nil && (err == nil || err.Error() != tt.wantErr.Error()) {
  438. t.Fatalf("BalanceAt(%x, %v) error = %q, want %q", tt.account, tt.block, err, tt.wantErr)
  439. }
  440. if got.Cmp(tt.want) != 0 {
  441. t.Fatalf("BalanceAt(%x, %v) = %v, want %v", tt.account, tt.block, got, tt.want)
  442. }
  443. })
  444. }
  445. }
  446. func testTransactionInBlockInterrupted(t *testing.T, client *rpc.Client) {
  447. ec := NewClient(client)
  448. // Get current block by number
  449. block, err := ec.BlockByNumber(context.Background(), nil)
  450. if err != nil {
  451. t.Fatalf("unexpected error: %v", err)
  452. }
  453. // Test tx in block interupted
  454. ctx, cancel := context.WithCancel(context.Background())
  455. cancel()
  456. tx, err := ec.TransactionInBlock(ctx, block.Hash(), 1)
  457. if tx != nil {
  458. t.Fatal("transaction should be nil")
  459. }
  460. if err == nil || err == ethereum.NotFound {
  461. t.Fatal("error should not be nil/notfound")
  462. }
  463. // Test tx in block not found
  464. if _, err := ec.TransactionInBlock(context.Background(), block.Hash(), 1); err != ethereum.NotFound {
  465. t.Fatal("error should be ethereum.NotFound")
  466. }
  467. }
  468. func testChainID(t *testing.T, client *rpc.Client) {
  469. ec := NewClient(client)
  470. id, err := ec.ChainID(context.Background())
  471. if err != nil {
  472. t.Fatalf("unexpected error: %v", err)
  473. }
  474. if id == nil || id.Cmp(params.AllEthashProtocolChanges.ChainID) != 0 {
  475. t.Fatalf("ChainID returned wrong number: %+v", id)
  476. }
  477. }
  478. func testGetBlock(t *testing.T, client *rpc.Client) {
  479. ec := NewClient(client)
  480. // Get current block number
  481. blockNumber, err := ec.BlockNumber(context.Background())
  482. if err != nil {
  483. t.Fatalf("unexpected error: %v", err)
  484. }
  485. if blockNumber != uint64(testBlockNum) {
  486. t.Fatalf("BlockNumber returned wrong number: %d", blockNumber)
  487. }
  488. // Get current block by number
  489. block, err := ec.BlockByNumber(context.Background(), new(big.Int).SetUint64(blockNumber))
  490. if err != nil {
  491. t.Fatalf("unexpected error: %v", err)
  492. }
  493. if block.NumberU64() != blockNumber {
  494. t.Fatalf("BlockByNumber returned wrong block: want %d got %d", blockNumber, block.NumberU64())
  495. }
  496. // Get current block by hash
  497. blockH, err := ec.BlockByHash(context.Background(), block.Hash())
  498. if err != nil {
  499. t.Fatalf("unexpected error: %v", err)
  500. }
  501. if block.Hash() != blockH.Hash() {
  502. t.Fatalf("BlockByHash returned wrong block: want %v got %v", block.Hash().Hex(), blockH.Hash().Hex())
  503. }
  504. // Get header by number
  505. header, err := ec.HeaderByNumber(context.Background(), new(big.Int).SetUint64(blockNumber))
  506. if err != nil {
  507. t.Fatalf("unexpected error: %v", err)
  508. }
  509. if block.Header().Hash() != header.Hash() {
  510. t.Fatalf("HeaderByNumber returned wrong header: want %v got %v", block.Header().Hash().Hex(), header.Hash().Hex())
  511. }
  512. // Get header by hash
  513. headerH, err := ec.HeaderByHash(context.Background(), block.Hash())
  514. if err != nil {
  515. t.Fatalf("unexpected error: %v", err)
  516. }
  517. if block.Header().Hash() != headerH.Hash() {
  518. t.Fatalf("HeaderByHash returned wrong header: want %v got %v", block.Header().Hash().Hex(), headerH.Hash().Hex())
  519. }
  520. }
  521. func testStatusFunctions(t *testing.T, client *rpc.Client) {
  522. ec := NewClient(client)
  523. // Sync progress
  524. progress, err := ec.SyncProgress(context.Background())
  525. if err != nil {
  526. t.Fatalf("unexpected error: %v", err)
  527. }
  528. if progress != nil {
  529. t.Fatalf("unexpected progress: %v", progress)
  530. }
  531. // NetworkID
  532. networkID, err := ec.NetworkID(context.Background())
  533. if err != nil {
  534. t.Fatalf("unexpected error: %v", err)
  535. }
  536. if networkID.Cmp(big.NewInt(0)) != 0 {
  537. t.Fatalf("unexpected networkID: %v", networkID)
  538. }
  539. // SuggestGasPrice (should suggest 1 Gwei)
  540. gasPrice, err := ec.SuggestGasPrice(context.Background())
  541. if err != nil {
  542. t.Fatalf("unexpected error: %v", err)
  543. }
  544. if gasPrice.Cmp(big.NewInt(1000000000)) != 0 {
  545. t.Fatalf("unexpected gas price: %v", gasPrice)
  546. }
  547. }
  548. func testCallContract(t *testing.T, client *rpc.Client) {
  549. ec := NewClient(client)
  550. // EstimateGas
  551. msg := ethereum.CallMsg{
  552. From: testAddr,
  553. To: &common.Address{},
  554. Gas: 21000,
  555. GasPrice: big.NewInt(1),
  556. Value: big.NewInt(1),
  557. }
  558. gas, err := ec.EstimateGas(context.Background(), msg)
  559. if err != nil {
  560. t.Fatalf("unexpected error: %v", err)
  561. }
  562. if gas != 21000 {
  563. t.Fatalf("unexpected gas price: %v", gas)
  564. }
  565. // CallContract
  566. if _, err := ec.CallContract(context.Background(), msg, big.NewInt(1)); err != nil {
  567. t.Fatalf("unexpected error: %v", err)
  568. }
  569. // PendingCallCOntract
  570. if _, err := ec.PendingCallContract(context.Background(), msg); err != nil {
  571. t.Fatalf("unexpected error: %v", err)
  572. }
  573. }
  574. func testDiffAccounts(t *testing.T, client *rpc.Client) {
  575. ec := NewClient(client)
  576. ctx, cancel := context.WithTimeout(context.Background(), 1000*time.Millisecond)
  577. defer cancel()
  578. for _, testBlock := range testBlocks {
  579. if testBlock.blockNr == 10 {
  580. continue
  581. }
  582. diffAccounts, err := ec.GetDiffAccounts(ctx, big.NewInt(int64(testBlock.blockNr)))
  583. if err != nil {
  584. t.Fatalf("unexpected error: %v", err)
  585. }
  586. accounts := make([]common.Address, 0)
  587. for _, tx := range testBlock.txs {
  588. // tx.to should be in the accounts list.
  589. for idx, account := range diffAccounts {
  590. if tx.to == account {
  591. break
  592. }
  593. if idx == len(diffAccounts)-1 {
  594. t.Fatalf("address(%v) expected in the diff account list, but not", tx.to)
  595. }
  596. }
  597. accounts = append(accounts, tx.to)
  598. }
  599. diffDetail, err := ec.GetDiffAccountsWithScope(ctx, big.NewInt(int64(testBlock.blockNr)), accounts)
  600. if err != nil {
  601. t.Fatalf("get diff accounts in block error: %v", err)
  602. }
  603. // No contract deposit tx, so expect empty transactions.
  604. if len(diffDetail.Transactions) != 0 {
  605. t.Fatalf("expect ignore all transactions, but some transaction has recorded")
  606. }
  607. }
  608. }