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