github.com/yuanzimu/bsc@v1.1.4/ethclient/ethclient_test.go (about)

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