github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/eth/filters/filter_system_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 filters
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"math/big"
    23  	"math/rand"
    24  	"reflect"
    25  	"runtime"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/scroll-tech/go-ethereum"
    30  	"github.com/scroll-tech/go-ethereum/common"
    31  	"github.com/scroll-tech/go-ethereum/consensus/ethash"
    32  	"github.com/scroll-tech/go-ethereum/core"
    33  	"github.com/scroll-tech/go-ethereum/core/bloombits"
    34  	"github.com/scroll-tech/go-ethereum/core/rawdb"
    35  	"github.com/scroll-tech/go-ethereum/core/types"
    36  	"github.com/scroll-tech/go-ethereum/core/vm"
    37  	"github.com/scroll-tech/go-ethereum/eth/ethconfig"
    38  	"github.com/scroll-tech/go-ethereum/ethdb"
    39  	"github.com/scroll-tech/go-ethereum/event"
    40  	"github.com/scroll-tech/go-ethereum/params"
    41  	"github.com/scroll-tech/go-ethereum/rpc"
    42  )
    43  
    44  var (
    45  	deadline = 5 * time.Minute
    46  )
    47  
    48  type testBackend struct {
    49  	mux             *event.TypeMux
    50  	db              ethdb.Database
    51  	sections        uint64
    52  	txFeed          event.Feed
    53  	logsFeed        event.Feed
    54  	rmLogsFeed      event.Feed
    55  	pendingLogsFeed event.Feed
    56  	chainFeed       event.Feed
    57  }
    58  
    59  func (b *testBackend) ChainDb() ethdb.Database {
    60  	return b.db
    61  }
    62  
    63  func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {
    64  	var (
    65  		hash common.Hash
    66  		num  uint64
    67  	)
    68  	if blockNr == rpc.LatestBlockNumber {
    69  		hash = rawdb.ReadHeadBlockHash(b.db)
    70  		number := rawdb.ReadHeaderNumber(b.db, hash)
    71  		if number == nil {
    72  			return nil, nil
    73  		}
    74  		num = *number
    75  	} else {
    76  		num = uint64(blockNr)
    77  		hash = rawdb.ReadCanonicalHash(b.db, num)
    78  	}
    79  	return rawdb.ReadHeader(b.db, hash, num), nil
    80  }
    81  
    82  func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
    83  	number := rawdb.ReadHeaderNumber(b.db, hash)
    84  	if number == nil {
    85  		return nil, nil
    86  	}
    87  	return rawdb.ReadHeader(b.db, hash, *number), nil
    88  }
    89  
    90  func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
    91  	if number := rawdb.ReadHeaderNumber(b.db, hash); number != nil {
    92  		return rawdb.ReadReceipts(b.db, hash, *number, params.TestChainConfig), nil
    93  	}
    94  	return nil, nil
    95  }
    96  
    97  func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
    98  	number := rawdb.ReadHeaderNumber(b.db, hash)
    99  	if number == nil {
   100  		return nil, nil
   101  	}
   102  	receipts := rawdb.ReadReceipts(b.db, hash, *number, params.TestChainConfig)
   103  
   104  	logs := make([][]*types.Log, len(receipts))
   105  	for i, receipt := range receipts {
   106  		logs[i] = receipt.Logs
   107  	}
   108  	return logs, nil
   109  }
   110  
   111  func (b *testBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
   112  	return b.txFeed.Subscribe(ch)
   113  }
   114  
   115  func (b *testBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
   116  	return b.rmLogsFeed.Subscribe(ch)
   117  }
   118  
   119  func (b *testBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
   120  	return b.logsFeed.Subscribe(ch)
   121  }
   122  
   123  func (b *testBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
   124  	return b.pendingLogsFeed.Subscribe(ch)
   125  }
   126  
   127  func (b *testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
   128  	return b.chainFeed.Subscribe(ch)
   129  }
   130  
   131  func (b *testBackend) BloomStatus() (uint64, uint64) {
   132  	return params.BloomBitsBlocks, b.sections
   133  }
   134  
   135  func (b *testBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {
   136  	requests := make(chan chan *bloombits.Retrieval)
   137  
   138  	go session.Multiplex(16, 0, requests)
   139  	go func() {
   140  		for {
   141  			// Wait for a service request or a shutdown
   142  			select {
   143  			case <-ctx.Done():
   144  				return
   145  
   146  			case request := <-requests:
   147  				task := <-request
   148  
   149  				task.Bitsets = make([][]byte, len(task.Sections))
   150  				for i, section := range task.Sections {
   151  					if rand.Int()%4 != 0 { // Handle occasional missing deliveries
   152  						head := rawdb.ReadCanonicalHash(b.db, (section+1)*params.BloomBitsBlocks-1)
   153  						task.Bitsets[i], _ = rawdb.ReadBloomBits(b.db, task.Bit, section, head)
   154  					}
   155  				}
   156  				request <- task
   157  			}
   158  		}
   159  	}()
   160  }
   161  
   162  // TestBlockSubscription tests if a block subscription returns block hashes for posted chain events.
   163  // It creates multiple subscriptions:
   164  // - one at the start and should receive all posted chain events and a second (blockHashes)
   165  // - one that is created after a cutoff moment and uninstalled after a second cutoff moment (blockHashes[cutoff1:cutoff2])
   166  // - one that is created after the second cutoff moment (blockHashes[cutoff2:])
   167  func TestBlockSubscription(t *testing.T) {
   168  	t.Parallel()
   169  
   170  	var (
   171  		db          = rawdb.NewMemoryDatabase()
   172  		backend     = &testBackend{db: db}
   173  		api         = NewPublicFilterAPI(backend, false, deadline, ethconfig.Defaults.MaxBlockRange)
   174  		genesis     = (&core.Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
   175  		chain, _    = core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 10, func(i int, gen *core.BlockGen) {})
   176  		chainEvents = []core.ChainEvent{}
   177  	)
   178  
   179  	for _, blk := range chain {
   180  		chainEvents = append(chainEvents, core.ChainEvent{Hash: blk.Hash(), Block: blk})
   181  	}
   182  
   183  	chan0 := make(chan *types.Header)
   184  	sub0 := api.events.SubscribeNewHeads(chan0)
   185  	chan1 := make(chan *types.Header)
   186  	sub1 := api.events.SubscribeNewHeads(chan1)
   187  
   188  	go func() { // simulate client
   189  		i1, i2 := 0, 0
   190  		for i1 != len(chainEvents) || i2 != len(chainEvents) {
   191  			select {
   192  			case header := <-chan0:
   193  				if chainEvents[i1].Hash != header.Hash() {
   194  					t.Errorf("sub0 received invalid hash on index %d, want %x, got %x", i1, chainEvents[i1].Hash, header.Hash())
   195  				}
   196  				i1++
   197  			case header := <-chan1:
   198  				if chainEvents[i2].Hash != header.Hash() {
   199  					t.Errorf("sub1 received invalid hash on index %d, want %x, got %x", i2, chainEvents[i2].Hash, header.Hash())
   200  				}
   201  				i2++
   202  			}
   203  		}
   204  
   205  		sub0.Unsubscribe()
   206  		sub1.Unsubscribe()
   207  	}()
   208  
   209  	time.Sleep(1 * time.Second)
   210  	for _, e := range chainEvents {
   211  		backend.chainFeed.Send(e)
   212  	}
   213  
   214  	<-sub0.Err()
   215  	<-sub1.Err()
   216  }
   217  
   218  // TestPendingTxFilter tests whether pending tx filters retrieve all pending transactions that are posted to the event mux.
   219  func TestPendingTxFilter(t *testing.T) {
   220  	t.Parallel()
   221  
   222  	var (
   223  		db      = rawdb.NewMemoryDatabase()
   224  		backend = &testBackend{db: db}
   225  		api     = NewPublicFilterAPI(backend, false, deadline, ethconfig.Defaults.MaxBlockRange)
   226  
   227  		transactions = []*types.Transaction{
   228  			types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
   229  			types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
   230  			types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
   231  			types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
   232  			types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
   233  		}
   234  
   235  		hashes []common.Hash
   236  	)
   237  
   238  	fid0 := api.NewPendingTransactionFilter()
   239  
   240  	time.Sleep(1 * time.Second)
   241  	backend.txFeed.Send(core.NewTxsEvent{Txs: transactions})
   242  
   243  	timeout := time.Now().Add(1 * time.Second)
   244  	for {
   245  		results, err := api.GetFilterChanges(fid0)
   246  		if err != nil {
   247  			t.Fatalf("Unable to retrieve logs: %v", err)
   248  		}
   249  
   250  		h := results.([]common.Hash)
   251  		hashes = append(hashes, h...)
   252  		if len(hashes) >= len(transactions) {
   253  			break
   254  		}
   255  		// check timeout
   256  		if time.Now().After(timeout) {
   257  			break
   258  		}
   259  
   260  		time.Sleep(100 * time.Millisecond)
   261  	}
   262  
   263  	if len(hashes) != len(transactions) {
   264  		t.Errorf("invalid number of transactions, want %d transactions(s), got %d", len(transactions), len(hashes))
   265  		return
   266  	}
   267  	for i := range hashes {
   268  		if hashes[i] != transactions[i].Hash() {
   269  			t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), hashes[i])
   270  		}
   271  	}
   272  }
   273  
   274  // TestLogFilterCreation test whether a given filter criteria makes sense.
   275  // If not it must return an error.
   276  func TestLogFilterCreation(t *testing.T) {
   277  	var (
   278  		db      = rawdb.NewMemoryDatabase()
   279  		backend = &testBackend{db: db}
   280  		api     = NewPublicFilterAPI(backend, false, deadline, ethconfig.Defaults.MaxBlockRange)
   281  
   282  		testCases = []struct {
   283  			crit    FilterCriteria
   284  			success bool
   285  		}{
   286  			// defaults
   287  			{FilterCriteria{}, true},
   288  			// valid block number range
   289  			{FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2)}, true},
   290  			// "mined" block range to pending
   291  			{FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, true},
   292  			// new mined and pending blocks
   293  			{FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, true},
   294  			// from block "higher" than to block
   295  			{FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(1)}, false},
   296  			// from block "higher" than to block
   297  			{FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false},
   298  			// from block "higher" than to block
   299  			{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false},
   300  			// from block "higher" than to block
   301  			{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, false},
   302  		}
   303  	)
   304  
   305  	for i, test := range testCases {
   306  		_, err := api.NewFilter(test.crit)
   307  		if test.success && err != nil {
   308  			t.Errorf("expected filter creation for case %d to success, got %v", i, err)
   309  		}
   310  		if !test.success && err == nil {
   311  			t.Errorf("expected testcase %d to fail with an error", i)
   312  		}
   313  	}
   314  }
   315  
   316  // TestInvalidLogFilterCreation tests whether invalid filter log criteria results in an error
   317  // when the filter is created.
   318  func TestInvalidLogFilterCreation(t *testing.T) {
   319  	t.Parallel()
   320  
   321  	var (
   322  		db      = rawdb.NewMemoryDatabase()
   323  		backend = &testBackend{db: db}
   324  		api     = NewPublicFilterAPI(backend, false, deadline, ethconfig.Defaults.MaxBlockRange)
   325  	)
   326  
   327  	// different situations where log filter creation should fail.
   328  	// Reason: fromBlock > toBlock
   329  	testCases := []FilterCriteria{
   330  		0: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
   331  		1: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)},
   332  		2: {FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)},
   333  	}
   334  
   335  	for i, test := range testCases {
   336  		if _, err := api.NewFilter(test); err == nil {
   337  			t.Errorf("Expected NewFilter for case #%d to fail", i)
   338  		}
   339  	}
   340  }
   341  
   342  func TestInvalidGetLogsRequest(t *testing.T) {
   343  	var (
   344  		db        = rawdb.NewMemoryDatabase()
   345  		backend   = &testBackend{db: db}
   346  		api       = NewPublicFilterAPI(backend, false, deadline, ethconfig.Defaults.MaxBlockRange)
   347  		blockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
   348  	)
   349  
   350  	// Reason: Cannot specify both BlockHash and FromBlock/ToBlock)
   351  	testCases := []FilterCriteria{
   352  		0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)},
   353  		1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)},
   354  		2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
   355  	}
   356  
   357  	for i, test := range testCases {
   358  		if _, err := api.GetLogs(context.Background(), test); err == nil {
   359  			t.Errorf("Expected Logs for case #%d to fail", i)
   360  		}
   361  	}
   362  }
   363  
   364  func TestGetLogsRange(t *testing.T) {
   365  	var (
   366  		db      = rawdb.NewMemoryDatabase()
   367  		backend = &testBackend{db: db}
   368  		api     = NewPublicFilterAPI(backend, false, deadline, 2)
   369  	)
   370  	(&core.Genesis{
   371  		Config: params.TestChainConfig,
   372  	}).MustCommit(db)
   373  	chain, _ := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil, false)
   374  	bs, _ := core.GenerateChain(params.TestChainConfig, chain.Genesis(), ethash.NewFaker(), db, 10, nil)
   375  	if _, err := chain.InsertChain(bs); err != nil {
   376  		panic(err)
   377  	}
   378  	// those test cases should fail because block range is greater then limit
   379  	failTestCases := []FilterCriteria{
   380  		// from 0 to 2 block
   381  		0: {FromBlock: big.NewInt(0), ToBlock: big.NewInt(2)},
   382  		// from 8 to latest block (10)
   383  		1: {FromBlock: big.NewInt(8)},
   384  		// from 0 to latest block (10)
   385  		2: {FromBlock: big.NewInt(0)},
   386  	}
   387  	for i, test := range failTestCases {
   388  		if _, err := api.GetLogs(context.Background(), test); err == nil {
   389  			t.Errorf("Expected Logs for failing case #%d to fail", i)
   390  		}
   391  	}
   392  
   393  	okTestCases := []FilterCriteria{
   394  		// from latest to latest block
   395  		0: {},
   396  		// from 9 to last block (10)
   397  		1: {FromBlock: big.NewInt(9)},
   398  		// from 3 to 4 block
   399  		2: {FromBlock: big.NewInt(3), ToBlock: big.NewInt(4)},
   400  	}
   401  	for i, test := range okTestCases {
   402  		if _, err := api.GetLogs(context.Background(), test); err != nil {
   403  			t.Errorf("Expected Logs for ok case #%d not to fail", i)
   404  		}
   405  	}
   406  }
   407  
   408  // TestLogFilter tests whether log filters match the correct logs that are posted to the event feed.
   409  func TestLogFilter(t *testing.T) {
   410  	t.Parallel()
   411  
   412  	var (
   413  		db      = rawdb.NewMemoryDatabase()
   414  		backend = &testBackend{db: db}
   415  		api     = NewPublicFilterAPI(backend, false, deadline, ethconfig.Defaults.MaxBlockRange)
   416  
   417  		firstAddr      = common.HexToAddress("0x1111111111111111111111111111111111111111")
   418  		secondAddr     = common.HexToAddress("0x2222222222222222222222222222222222222222")
   419  		thirdAddress   = common.HexToAddress("0x3333333333333333333333333333333333333333")
   420  		notUsedAddress = common.HexToAddress("0x9999999999999999999999999999999999999999")
   421  		firstTopic     = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
   422  		secondTopic    = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222")
   423  		notUsedTopic   = common.HexToHash("0x9999999999999999999999999999999999999999999999999999999999999999")
   424  
   425  		// posted twice, once as regular logs and once as pending logs.
   426  		allLogs = []*types.Log{
   427  			{Address: firstAddr},
   428  			{Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 1},
   429  			{Address: secondAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 1},
   430  			{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 2},
   431  			{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 3},
   432  		}
   433  
   434  		expectedCase7  = []*types.Log{allLogs[3], allLogs[4], allLogs[0], allLogs[1], allLogs[2], allLogs[3], allLogs[4]}
   435  		expectedCase11 = []*types.Log{allLogs[1], allLogs[2], allLogs[1], allLogs[2]}
   436  
   437  		testCases = []struct {
   438  			crit     FilterCriteria
   439  			expected []*types.Log
   440  			id       rpc.ID
   441  		}{
   442  			// match all
   443  			0: {FilterCriteria{}, allLogs, ""},
   444  			// match none due to no matching addresses
   445  			1: {FilterCriteria{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}}, []*types.Log{}, ""},
   446  			// match logs based on addresses, ignore topics
   447  			2: {FilterCriteria{Addresses: []common.Address{firstAddr}}, allLogs[:2], ""},
   448  			// match none due to no matching topics (match with address)
   449  			3: {FilterCriteria{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}}, []*types.Log{}, ""},
   450  			// match logs based on addresses and topics
   451  			4: {FilterCriteria{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[3:5], ""},
   452  			// match logs based on multiple addresses and "or" topics
   453  			5: {FilterCriteria{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[2:5], ""},
   454  			// logs in the pending block
   455  			6: {FilterCriteria{Addresses: []common.Address{firstAddr}, FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, allLogs[:2], ""},
   456  			// mined logs with block num >= 2 or pending logs
   457  			7: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, expectedCase7, ""},
   458  			// all "mined" logs with block num >= 2
   459  			8: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, allLogs[3:], ""},
   460  			// all "mined" logs
   461  			9: {FilterCriteria{ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, allLogs, ""},
   462  			// all "mined" logs with 1>= block num <=2 and topic secondTopic
   463  			10: {FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2), Topics: [][]common.Hash{{secondTopic}}}, allLogs[3:4], ""},
   464  			// all "mined" and pending logs with topic firstTopic
   465  			11: {FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), Topics: [][]common.Hash{{firstTopic}}}, expectedCase11, ""},
   466  			// match all logs due to wildcard topic
   467  			12: {FilterCriteria{Topics: [][]common.Hash{nil}}, allLogs[1:], ""},
   468  		}
   469  	)
   470  
   471  	// create all filters
   472  	for i := range testCases {
   473  		testCases[i].id, _ = api.NewFilter(testCases[i].crit)
   474  	}
   475  
   476  	// raise events
   477  	time.Sleep(1 * time.Second)
   478  	if nsend := backend.logsFeed.Send(allLogs); nsend == 0 {
   479  		t.Fatal("Logs event not delivered")
   480  	}
   481  	if nsend := backend.pendingLogsFeed.Send(allLogs); nsend == 0 {
   482  		t.Fatal("Pending logs event not delivered")
   483  	}
   484  
   485  	for i, tt := range testCases {
   486  		var fetched []*types.Log
   487  		timeout := time.Now().Add(1 * time.Second)
   488  		for { // fetch all expected logs
   489  			results, err := api.GetFilterChanges(tt.id)
   490  			if err != nil {
   491  				t.Fatalf("Unable to fetch logs: %v", err)
   492  			}
   493  
   494  			fetched = append(fetched, results.([]*types.Log)...)
   495  			if len(fetched) >= len(tt.expected) {
   496  				break
   497  			}
   498  			// check timeout
   499  			if time.Now().After(timeout) {
   500  				break
   501  			}
   502  
   503  			time.Sleep(100 * time.Millisecond)
   504  		}
   505  
   506  		if len(fetched) != len(tt.expected) {
   507  			t.Errorf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched))
   508  			return
   509  		}
   510  
   511  		for l := range fetched {
   512  			if fetched[l].Removed {
   513  				t.Errorf("expected log not to be removed for log %d in case %d", l, i)
   514  			}
   515  			if !reflect.DeepEqual(fetched[l], tt.expected[l]) {
   516  				t.Errorf("invalid log on index %d for case %d", l, i)
   517  			}
   518  		}
   519  	}
   520  }
   521  
   522  // TestPendingLogsSubscription tests if a subscription receives the correct pending logs that are posted to the event feed.
   523  func TestPendingLogsSubscription(t *testing.T) {
   524  	t.Parallel()
   525  
   526  	var (
   527  		db      = rawdb.NewMemoryDatabase()
   528  		backend = &testBackend{db: db}
   529  		api     = NewPublicFilterAPI(backend, false, deadline, ethconfig.Defaults.MaxBlockRange)
   530  
   531  		firstAddr      = common.HexToAddress("0x1111111111111111111111111111111111111111")
   532  		secondAddr     = common.HexToAddress("0x2222222222222222222222222222222222222222")
   533  		thirdAddress   = common.HexToAddress("0x3333333333333333333333333333333333333333")
   534  		notUsedAddress = common.HexToAddress("0x9999999999999999999999999999999999999999")
   535  		firstTopic     = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
   536  		secondTopic    = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222")
   537  		thirdTopic     = common.HexToHash("0x3333333333333333333333333333333333333333333333333333333333333333")
   538  		fourthTopic    = common.HexToHash("0x4444444444444444444444444444444444444444444444444444444444444444")
   539  		notUsedTopic   = common.HexToHash("0x9999999999999999999999999999999999999999999999999999999999999999")
   540  
   541  		allLogs = [][]*types.Log{
   542  			{{Address: firstAddr, Topics: []common.Hash{}, BlockNumber: 0}},
   543  			{{Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 1}},
   544  			{{Address: secondAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 2}},
   545  			{{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 3}},
   546  			{{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 4}},
   547  			{
   548  				{Address: thirdAddress, Topics: []common.Hash{firstTopic}, BlockNumber: 5},
   549  				{Address: thirdAddress, Topics: []common.Hash{thirdTopic}, BlockNumber: 5},
   550  				{Address: thirdAddress, Topics: []common.Hash{fourthTopic}, BlockNumber: 5},
   551  				{Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 5},
   552  			},
   553  		}
   554  
   555  		pendingBlockNumber = big.NewInt(rpc.PendingBlockNumber.Int64())
   556  
   557  		testCases = []struct {
   558  			crit     ethereum.FilterQuery
   559  			expected []*types.Log
   560  			c        chan []*types.Log
   561  			sub      *Subscription
   562  			err      chan error
   563  		}{
   564  			// match all
   565  			{
   566  				ethereum.FilterQuery{FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
   567  				flattenLogs(allLogs),
   568  				nil, nil, nil,
   569  			},
   570  			// match none due to no matching addresses
   571  			{
   572  				ethereum.FilterQuery{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
   573  				nil,
   574  				nil, nil, nil,
   575  			},
   576  			// match logs based on addresses, ignore topics
   577  			{
   578  				ethereum.FilterQuery{Addresses: []common.Address{firstAddr}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
   579  				append(flattenLogs(allLogs[:2]), allLogs[5][3]),
   580  				nil, nil, nil,
   581  			},
   582  			// match none due to no matching topics (match with address)
   583  			{
   584  				ethereum.FilterQuery{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
   585  				nil,
   586  				nil, nil, nil,
   587  			},
   588  			// match logs based on addresses and topics
   589  			{
   590  				ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
   591  				append(flattenLogs(allLogs[3:5]), allLogs[5][0]),
   592  				nil, nil, nil,
   593  			},
   594  			// match logs based on multiple addresses and "or" topics
   595  			{
   596  				ethereum.FilterQuery{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
   597  				append(flattenLogs(allLogs[2:5]), allLogs[5][0]),
   598  				nil, nil, nil,
   599  			},
   600  			// multiple pending logs, should match only 2 topics from the logs in block 5
   601  			{
   602  				ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, fourthTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
   603  				[]*types.Log{allLogs[5][0], allLogs[5][2]},
   604  				nil, nil, nil,
   605  			},
   606  			// match none due to only matching new mined logs
   607  			{
   608  				ethereum.FilterQuery{},
   609  				nil,
   610  				nil, nil, nil,
   611  			},
   612  			// match none due to only matching mined logs within a specific block range
   613  			{
   614  				ethereum.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2)},
   615  				nil,
   616  				nil, nil, nil,
   617  			},
   618  			// match all due to matching mined and pending logs
   619  			{
   620  				ethereum.FilterQuery{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())},
   621  				flattenLogs(allLogs),
   622  				nil, nil, nil,
   623  			},
   624  			// match none due to matching logs from a specific block number to new mined blocks
   625  			{
   626  				ethereum.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
   627  				nil,
   628  				nil, nil, nil,
   629  			},
   630  		}
   631  	)
   632  
   633  	// create all subscriptions, this ensures all subscriptions are created before the events are posted.
   634  	// on slow machines this could otherwise lead to missing events when the subscription is created after
   635  	// (some) events are posted.
   636  	for i := range testCases {
   637  		testCases[i].c = make(chan []*types.Log)
   638  		testCases[i].err = make(chan error)
   639  
   640  		var err error
   641  		testCases[i].sub, err = api.events.SubscribeLogs(testCases[i].crit, testCases[i].c)
   642  		if err != nil {
   643  			t.Fatalf("SubscribeLogs %d failed: %v\n", i, err)
   644  		}
   645  	}
   646  
   647  	for n, test := range testCases {
   648  		i := n
   649  		tt := test
   650  		go func() {
   651  			defer tt.sub.Unsubscribe()
   652  
   653  			var fetched []*types.Log
   654  
   655  			timeout := time.After(1 * time.Second)
   656  		fetchLoop:
   657  			for {
   658  				select {
   659  				case logs := <-tt.c:
   660  					// Do not break early if we've fetched greater, or equal,
   661  					// to the number of logs expected. This ensures we do not
   662  					// deadlock the filter system because it will do a blocking
   663  					// send on this channel if another log arrives.
   664  					fetched = append(fetched, logs...)
   665  				case <-timeout:
   666  					break fetchLoop
   667  				}
   668  			}
   669  
   670  			if len(fetched) != len(tt.expected) {
   671  				tt.err <- fmt.Errorf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched))
   672  				return
   673  			}
   674  
   675  			for l := range fetched {
   676  				if fetched[l].Removed {
   677  					tt.err <- fmt.Errorf("expected log not to be removed for log %d in case %d", l, i)
   678  					return
   679  				}
   680  				if !reflect.DeepEqual(fetched[l], tt.expected[l]) {
   681  					tt.err <- fmt.Errorf("invalid log on index %d for case %d\n", l, i)
   682  					return
   683  				}
   684  			}
   685  			tt.err <- nil
   686  		}()
   687  	}
   688  
   689  	// raise events
   690  	for _, ev := range allLogs {
   691  		backend.pendingLogsFeed.Send(ev)
   692  	}
   693  
   694  	for i := range testCases {
   695  		err := <-testCases[i].err
   696  		if err != nil {
   697  			t.Fatalf("test %d failed: %v", i, err)
   698  		}
   699  		<-testCases[i].sub.Err()
   700  	}
   701  }
   702  
   703  // TestPendingTxFilterDeadlock tests if the event loop hangs when pending
   704  // txes arrive at the same time that one of multiple filters is timing out.
   705  // Please refer to #22131 for more details.
   706  func TestPendingTxFilterDeadlock(t *testing.T) {
   707  	t.Parallel()
   708  	timeout := 100 * time.Millisecond
   709  
   710  	var (
   711  		db      = rawdb.NewMemoryDatabase()
   712  		backend = &testBackend{db: db}
   713  		api     = NewPublicFilterAPI(backend, false, timeout, ethconfig.Defaults.MaxBlockRange)
   714  		done    = make(chan struct{})
   715  	)
   716  
   717  	go func() {
   718  		// Bombard feed with txes until signal was received to stop
   719  		i := uint64(0)
   720  		for {
   721  			select {
   722  			case <-done:
   723  				return
   724  			default:
   725  			}
   726  
   727  			tx := types.NewTransaction(i, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil)
   728  			backend.txFeed.Send(core.NewTxsEvent{Txs: []*types.Transaction{tx}})
   729  			i++
   730  		}
   731  	}()
   732  
   733  	// Create a bunch of filters that will
   734  	// timeout either in 100ms or 200ms
   735  	fids := make([]rpc.ID, 20)
   736  	for i := 0; i < len(fids); i++ {
   737  		fid := api.NewPendingTransactionFilter()
   738  		fids[i] = fid
   739  		// Wait for at least one tx to arrive in filter
   740  		for {
   741  			hashes, err := api.GetFilterChanges(fid)
   742  			if err != nil {
   743  				t.Fatalf("Filter should exist: %v\n", err)
   744  			}
   745  			if len(hashes.([]common.Hash)) > 0 {
   746  				break
   747  			}
   748  			runtime.Gosched()
   749  		}
   750  	}
   751  
   752  	// Wait until filters have timed out
   753  	time.Sleep(3 * timeout)
   754  
   755  	// If tx loop doesn't consume `done` after a second
   756  	// it's hanging.
   757  	select {
   758  	case done <- struct{}{}:
   759  		// Check that all filters have been uninstalled
   760  		for _, fid := range fids {
   761  			if _, err := api.GetFilterChanges(fid); err == nil {
   762  				t.Errorf("Filter %s should have been uninstalled\n", fid)
   763  			}
   764  		}
   765  	case <-time.After(1 * time.Second):
   766  		t.Error("Tx sending loop hangs")
   767  	}
   768  }
   769  
   770  func flattenLogs(pl [][]*types.Log) []*types.Log {
   771  	var logs []*types.Log
   772  	for _, l := range pl {
   773  		logs = append(logs, l...)
   774  	}
   775  	return logs
   776  }