github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/eth/filters/filter_system_test.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:38</date>
    10  //</624342635624009728>
    11  
    12  
    13  package filters
    14  
    15  import (
    16  	"context"
    17  	"fmt"
    18  	"math/big"
    19  	"math/rand"
    20  	"reflect"
    21  	"testing"
    22  	"time"
    23  
    24  	ethereum "github.com/ethereum/go-ethereum"
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/consensus/ethash"
    27  	"github.com/ethereum/go-ethereum/core"
    28  	"github.com/ethereum/go-ethereum/core/bloombits"
    29  	"github.com/ethereum/go-ethereum/core/rawdb"
    30  	"github.com/ethereum/go-ethereum/core/types"
    31  	"github.com/ethereum/go-ethereum/ethdb"
    32  	"github.com/ethereum/go-ethereum/event"
    33  	"github.com/ethereum/go-ethereum/params"
    34  	"github.com/ethereum/go-ethereum/rpc"
    35  )
    36  
    37  type testBackend struct {
    38  	mux        *event.TypeMux
    39  	db         ethdb.Database
    40  	sections   uint64
    41  	txFeed     *event.Feed
    42  	rmLogsFeed *event.Feed
    43  	logsFeed   *event.Feed
    44  	chainFeed  *event.Feed
    45  }
    46  
    47  func (b *testBackend) ChainDb() ethdb.Database {
    48  	return b.db
    49  }
    50  
    51  func (b *testBackend) EventMux() *event.TypeMux {
    52  	return b.mux
    53  }
    54  
    55  func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {
    56  	var (
    57  		hash common.Hash
    58  		num  uint64
    59  	)
    60  	if blockNr == rpc.LatestBlockNumber {
    61  		hash = rawdb.ReadHeadBlockHash(b.db)
    62  		number := rawdb.ReadHeaderNumber(b.db, hash)
    63  		if number == nil {
    64  			return nil, nil
    65  		}
    66  		num = *number
    67  	} else {
    68  		num = uint64(blockNr)
    69  		hash = rawdb.ReadCanonicalHash(b.db, num)
    70  	}
    71  	return rawdb.ReadHeader(b.db, hash, num), nil
    72  }
    73  
    74  func (b *testBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
    75  	number := rawdb.ReadHeaderNumber(b.db, hash)
    76  	if number == nil {
    77  		return nil, nil
    78  	}
    79  	return rawdb.ReadHeader(b.db, hash, *number), nil
    80  }
    81  
    82  func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
    83  	if number := rawdb.ReadHeaderNumber(b.db, hash); number != nil {
    84  		return rawdb.ReadReceipts(b.db, hash, *number), nil
    85  	}
    86  	return nil, nil
    87  }
    88  
    89  func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
    90  	number := rawdb.ReadHeaderNumber(b.db, hash)
    91  	if number == nil {
    92  		return nil, nil
    93  	}
    94  	receipts := rawdb.ReadReceipts(b.db, hash, *number)
    95  
    96  	logs := make([][]*types.Log, len(receipts))
    97  	for i, receipt := range receipts {
    98  		logs[i] = receipt.Logs
    99  	}
   100  	return logs, nil
   101  }
   102  
   103  func (b *testBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
   104  	return b.txFeed.Subscribe(ch)
   105  }
   106  
   107  func (b *testBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
   108  	return b.rmLogsFeed.Subscribe(ch)
   109  }
   110  
   111  func (b *testBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
   112  	return b.logsFeed.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  //等待服务请求或关闭
   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 { //处理偶尔丢失的交货
   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  //testblocksubscription测试块订阅是否返回已发布链事件的块哈希。
   151  //它创建多个订阅:
   152  //-一个在开始处,应接收所有已发布的链事件和一秒钟(blockhash)
   153  //-在切断力矩后创建,在第二个切断力矩后卸载(blockhashes[cutoff1:cutoff2])
   154  //-在第二个截止力矩后创建的一个(blockhashes[cutoff2:]
   155  func TestBlockSubscription(t *testing.T) {
   156  	t.Parallel()
   157  
   158  	var (
   159  		mux         = new(event.TypeMux)
   160  		db          = ethdb.NewMemDatabase()
   161  		txFeed      = new(event.Feed)
   162  		rmLogsFeed  = new(event.Feed)
   163  		logsFeed    = new(event.Feed)
   164  		chainFeed   = new(event.Feed)
   165  		backend     = &testBackend{mux, db, 0, txFeed, rmLogsFeed, logsFeed, chainFeed}
   166  		api         = NewPublicFilterAPI(backend, false)
   167  		genesis     = new(core.Genesis).MustCommit(db)
   168  		chain, _    = core.GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 10, func(i int, gen *core.BlockGen) {})
   169  		chainEvents = []core.ChainEvent{}
   170  	)
   171  
   172  	for _, blk := range chain {
   173  		chainEvents = append(chainEvents, core.ChainEvent{Hash: blk.Hash(), Block: blk})
   174  	}
   175  
   176  	chan0 := make(chan *types.Header)
   177  	sub0 := api.events.SubscribeNewHeads(chan0)
   178  	chan1 := make(chan *types.Header)
   179  	sub1 := api.events.SubscribeNewHeads(chan1)
   180  
   181  go func() { //模拟客户端
   182  		i1, i2 := 0, 0
   183  		for i1 != len(chainEvents) || i2 != len(chainEvents) {
   184  			select {
   185  			case header := <-chan0:
   186  				if chainEvents[i1].Hash != header.Hash() {
   187  					t.Errorf("sub0 received invalid hash on index %d, want %x, got %x", i1, chainEvents[i1].Hash, header.Hash())
   188  				}
   189  				i1++
   190  			case header := <-chan1:
   191  				if chainEvents[i2].Hash != header.Hash() {
   192  					t.Errorf("sub1 received invalid hash on index %d, want %x, got %x", i2, chainEvents[i2].Hash, header.Hash())
   193  				}
   194  				i2++
   195  			}
   196  		}
   197  
   198  		sub0.Unsubscribe()
   199  		sub1.Unsubscribe()
   200  	}()
   201  
   202  	time.Sleep(1 * time.Second)
   203  	for _, e := range chainEvents {
   204  		chainFeed.Send(e)
   205  	}
   206  
   207  	<-sub0.Err()
   208  	<-sub1.Err()
   209  }
   210  
   211  //testpendingtxfilter测试挂起的tx筛选器是否检索发布到事件mux的所有挂起事务。
   212  func TestPendingTxFilter(t *testing.T) {
   213  	t.Parallel()
   214  
   215  	var (
   216  		mux        = new(event.TypeMux)
   217  		db         = ethdb.NewMemDatabase()
   218  		txFeed     = new(event.Feed)
   219  		rmLogsFeed = new(event.Feed)
   220  		logsFeed   = new(event.Feed)
   221  		chainFeed  = new(event.Feed)
   222  		backend    = &testBackend{mux, db, 0, txFeed, rmLogsFeed, logsFeed, chainFeed}
   223  		api        = NewPublicFilterAPI(backend, false)
   224  
   225  		transactions = []*types.Transaction{
   226  			types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
   227  			types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
   228  			types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
   229  			types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
   230  			types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
   231  		}
   232  
   233  		hashes []common.Hash
   234  	)
   235  
   236  	fid0 := api.NewPendingTransactionFilter()
   237  
   238  	time.Sleep(1 * time.Second)
   239  	txFeed.Send(core.NewTxsEvent{Txs: transactions})
   240  
   241  	timeout := time.Now().Add(1 * time.Second)
   242  	for {
   243  		results, err := api.GetFilterChanges(fid0)
   244  		if err != nil {
   245  			t.Fatalf("Unable to retrieve logs: %v", err)
   246  		}
   247  
   248  		h := results.([]common.Hash)
   249  		hashes = append(hashes, h...)
   250  		if len(hashes) >= len(transactions) {
   251  			break
   252  		}
   253  //检查超时
   254  		if time.Now().After(timeout) {
   255  			break
   256  		}
   257  
   258  		time.Sleep(100 * time.Millisecond)
   259  	}
   260  
   261  	if len(hashes) != len(transactions) {
   262  		t.Errorf("invalid number of transactions, want %d transactions(s), got %d", len(transactions), len(hashes))
   263  		return
   264  	}
   265  	for i := range hashes {
   266  		if hashes[i] != transactions[i].Hash() {
   267  			t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), hashes[i])
   268  		}
   269  	}
   270  }
   271  
   272  //testlogfiltercreation测试给定的筛选条件是否有意义。
   273  //否则,它必须返回一个错误。
   274  func TestLogFilterCreation(t *testing.T) {
   275  	var (
   276  		mux        = new(event.TypeMux)
   277  		db         = ethdb.NewMemDatabase()
   278  		txFeed     = new(event.Feed)
   279  		rmLogsFeed = new(event.Feed)
   280  		logsFeed   = new(event.Feed)
   281  		chainFeed  = new(event.Feed)
   282  		backend    = &testBackend{mux, db, 0, txFeed, rmLogsFeed, logsFeed, chainFeed}
   283  		api        = NewPublicFilterAPI(backend, false)
   284  
   285  		testCases = []struct {
   286  			crit    FilterCriteria
   287  			success bool
   288  		}{
   289  //默认值
   290  			{FilterCriteria{}, true},
   291  //有效的块编号范围
   292  			{FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2)}, true},
   293  //“已开采”区块范围待定
   294  			{FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, true},
   295  //新建已开采和待定区块
   296  			{FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, true},
   297  //从“高”区到“高”区
   298  			{FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(1)}, false},
   299  //从“高”区到“高”区
   300  			{FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false},
   301  //从“高”区到“高”区
   302  			{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false},
   303  //从“高”区到“高”区
   304  			{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, false},
   305  		}
   306  	)
   307  
   308  	for i, test := range testCases {
   309  		_, err := api.NewFilter(test.crit)
   310  		if test.success && err != nil {
   311  			t.Errorf("expected filter creation for case %d to success, got %v", i, err)
   312  		}
   313  		if !test.success && err == nil {
   314  			t.Errorf("expected testcase %d to fail with an error", i)
   315  		}
   316  	}
   317  }
   318  
   319  //TestInvalidLogFilterCreation测试无效的筛选器日志条件是否导致错误
   320  //创建筛选器时。
   321  func TestInvalidLogFilterCreation(t *testing.T) {
   322  	t.Parallel()
   323  
   324  	var (
   325  		mux        = new(event.TypeMux)
   326  		db         = ethdb.NewMemDatabase()
   327  		txFeed     = new(event.Feed)
   328  		rmLogsFeed = new(event.Feed)
   329  		logsFeed   = new(event.Feed)
   330  		chainFeed  = new(event.Feed)
   331  		backend    = &testBackend{mux, db, 0, txFeed, rmLogsFeed, logsFeed, chainFeed}
   332  		api        = NewPublicFilterAPI(backend, false)
   333  	)
   334  
   335  //日志过滤器创建失败的不同情况。
   336  //原因:FromBlock>ToBlock
   337  	testCases := []FilterCriteria{
   338  		0: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
   339  		1: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)},
   340  		2: {FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)},
   341  	}
   342  
   343  	for i, test := range testCases {
   344  		if _, err := api.NewFilter(test); err == nil {
   345  			t.Errorf("Expected NewFilter for case #%d to fail", i)
   346  		}
   347  	}
   348  }
   349  
   350  func TestInvalidGetLogsRequest(t *testing.T) {
   351  	var (
   352  		mux        = new(event.TypeMux)
   353  		db         = ethdb.NewMemDatabase()
   354  		txFeed     = new(event.Feed)
   355  		rmLogsFeed = new(event.Feed)
   356  		logsFeed   = new(event.Feed)
   357  		chainFeed  = new(event.Feed)
   358  		backend    = &testBackend{mux, db, 0, txFeed, rmLogsFeed, logsFeed, chainFeed}
   359  		api        = NewPublicFilterAPI(backend, false)
   360  		blockHash  = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
   361  	)
   362  
   363  //原因:不能同时指定blockhash和fromblock/toblock)
   364  	testCases := []FilterCriteria{
   365  		0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)},
   366  		1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)},
   367  		2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
   368  	}
   369  
   370  	for i, test := range testCases {
   371  		if _, err := api.GetLogs(context.Background(), test); err == nil {
   372  			t.Errorf("Expected Logs for case #%d to fail", i)
   373  		}
   374  	}
   375  }
   376  
   377  //testlogfilter测试日志筛选器是否匹配发布到事件馈送的正确日志。
   378  func TestLogFilter(t *testing.T) {
   379  	t.Parallel()
   380  
   381  	var (
   382  		mux        = new(event.TypeMux)
   383  		db         = ethdb.NewMemDatabase()
   384  		txFeed     = new(event.Feed)
   385  		rmLogsFeed = new(event.Feed)
   386  		logsFeed   = new(event.Feed)
   387  		chainFeed  = new(event.Feed)
   388  		backend    = &testBackend{mux, db, 0, txFeed, rmLogsFeed, logsFeed, chainFeed}
   389  		api        = NewPublicFilterAPI(backend, false)
   390  
   391  		firstAddr      = common.HexToAddress("0x1111111111111111111111111111111111111111")
   392  		secondAddr     = common.HexToAddress("0x2222222222222222222222222222222222222222")
   393  		thirdAddress   = common.HexToAddress("0x3333333333333333333333333333333333333333")
   394  		notUsedAddress = common.HexToAddress("0x9999999999999999999999999999999999999999")
   395  		firstTopic     = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
   396  		secondTopic    = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222")
   397  		notUsedTopic   = common.HexToHash("0x9999999999999999999999999999999999999999999999999999999999999999")
   398  
   399  //发布两次,一次作为vm.logs,一次作为core.pendinglogsevent
   400  		allLogs = []*types.Log{
   401  			{Address: firstAddr},
   402  			{Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 1},
   403  			{Address: secondAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 1},
   404  			{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 2},
   405  			{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 3},
   406  		}
   407  
   408  		expectedCase7  = []*types.Log{allLogs[3], allLogs[4], allLogs[0], allLogs[1], allLogs[2], allLogs[3], allLogs[4]}
   409  		expectedCase11 = []*types.Log{allLogs[1], allLogs[2], allLogs[1], allLogs[2]}
   410  
   411  		testCases = []struct {
   412  			crit     FilterCriteria
   413  			expected []*types.Log
   414  			id       rpc.ID
   415  		}{
   416  //全部匹配
   417  			0: {FilterCriteria{}, allLogs, ""},
   418  //由于没有匹配的地址而不匹配
   419  			1: {FilterCriteria{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}}, []*types.Log{}, ""},
   420  //根据地址匹配日志,忽略主题
   421  			2: {FilterCriteria{Addresses: []common.Address{firstAddr}}, allLogs[:2], ""},
   422  //由于没有匹配的主题(与地址匹配),因此不匹配
   423  			3: {FilterCriteria{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}}, []*types.Log{}, ""},
   424  //根据地址和主题匹配日志
   425  			4: {FilterCriteria{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[3:5], ""},
   426  //基于多个地址和“或”主题匹配日志
   427  			5: {FilterCriteria{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[2:5], ""},
   428  //在挂起块中登录
   429  			6: {FilterCriteria{Addresses: []common.Address{firstAddr}, FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, allLogs[:2], ""},
   430  //块数大于等于2或挂起日志的挖掘日志
   431  			7: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, expectedCase7, ""},
   432  //块数大于等于2的所有“已开采”日志
   433  			8: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, allLogs[3:], ""},
   434  //所有“开采”的原木
   435  			9: {FilterCriteria{ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, allLogs, ""},
   436  //所有“已挖掘”日志,其中1>=block num<=2和topic secondtopic
   437  			10: {FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2), Topics: [][]common.Hash{{secondTopic}}}, allLogs[3:4], ""},
   438  //主题为FirstTopic的所有“已挖掘”和挂起日志
   439  			11: {FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), Topics: [][]common.Hash{{firstTopic}}}, expectedCase11, ""},
   440  //根据通配符主题匹配所有日志
   441  			12: {FilterCriteria{Topics: [][]common.Hash{nil}}, allLogs[1:], ""},
   442  		}
   443  	)
   444  
   445  //创建所有筛选器
   446  	for i := range testCases {
   447  		testCases[i].id, _ = api.NewFilter(testCases[i].crit)
   448  	}
   449  
   450  //提高事件
   451  	time.Sleep(1 * time.Second)
   452  	if nsend := logsFeed.Send(allLogs); nsend == 0 {
   453  		t.Fatal("Shoud have at least one subscription")
   454  	}
   455  	if err := mux.Post(core.PendingLogsEvent{Logs: allLogs}); err != nil {
   456  		t.Fatal(err)
   457  	}
   458  
   459  	for i, tt := range testCases {
   460  		var fetched []*types.Log
   461  		timeout := time.Now().Add(1 * time.Second)
   462  for { //获取所有预期日志
   463  			results, err := api.GetFilterChanges(tt.id)
   464  			if err != nil {
   465  				t.Fatalf("Unable to fetch logs: %v", err)
   466  			}
   467  
   468  			fetched = append(fetched, results.([]*types.Log)...)
   469  			if len(fetched) >= len(tt.expected) {
   470  				break
   471  			}
   472  //检查超时
   473  			if time.Now().After(timeout) {
   474  				break
   475  			}
   476  
   477  			time.Sleep(100 * time.Millisecond)
   478  		}
   479  
   480  		if len(fetched) != len(tt.expected) {
   481  			t.Errorf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched))
   482  			return
   483  		}
   484  
   485  		for l := range fetched {
   486  			if fetched[l].Removed {
   487  				t.Errorf("expected log not to be removed for log %d in case %d", l, i)
   488  			}
   489  			if !reflect.DeepEqual(fetched[l], tt.expected[l]) {
   490  				t.Errorf("invalid log on index %d for case %d", l, i)
   491  			}
   492  		}
   493  	}
   494  }
   495  
   496  //testpendinglogssubscription测试订阅是否接收到发布到事件源的正确挂起日志。
   497  func TestPendingLogsSubscription(t *testing.T) {
   498  	t.Parallel()
   499  
   500  	var (
   501  		mux        = new(event.TypeMux)
   502  		db         = ethdb.NewMemDatabase()
   503  		txFeed     = new(event.Feed)
   504  		rmLogsFeed = new(event.Feed)
   505  		logsFeed   = new(event.Feed)
   506  		chainFeed  = new(event.Feed)
   507  		backend    = &testBackend{mux, db, 0, txFeed, rmLogsFeed, logsFeed, chainFeed}
   508  		api        = NewPublicFilterAPI(backend, false)
   509  
   510  		firstAddr      = common.HexToAddress("0x1111111111111111111111111111111111111111")
   511  		secondAddr     = common.HexToAddress("0x2222222222222222222222222222222222222222")
   512  		thirdAddress   = common.HexToAddress("0x3333333333333333333333333333333333333333")
   513  		notUsedAddress = common.HexToAddress("0x9999999999999999999999999999999999999999")
   514  		firstTopic     = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
   515  		secondTopic    = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222")
   516  		thirdTopic     = common.HexToHash("0x3333333333333333333333333333333333333333333333333333333333333333")
   517  		fourthTopic    = common.HexToHash("0x4444444444444444444444444444444444444444444444444444444444444444")
   518  		notUsedTopic   = common.HexToHash("0x9999999999999999999999999999999999999999999999999999999999999999")
   519  
   520  		allLogs = []core.PendingLogsEvent{
   521  			{Logs: []*types.Log{{Address: firstAddr, Topics: []common.Hash{}, BlockNumber: 0}}},
   522  			{Logs: []*types.Log{{Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 1}}},
   523  			{Logs: []*types.Log{{Address: secondAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 2}}},
   524  			{Logs: []*types.Log{{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 3}}},
   525  			{Logs: []*types.Log{{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 4}}},
   526  			{Logs: []*types.Log{
   527  				{Address: thirdAddress, Topics: []common.Hash{firstTopic}, BlockNumber: 5},
   528  				{Address: thirdAddress, Topics: []common.Hash{thirdTopic}, BlockNumber: 5},
   529  				{Address: thirdAddress, Topics: []common.Hash{fourthTopic}, BlockNumber: 5},
   530  				{Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 5},
   531  			}},
   532  		}
   533  
   534  		convertLogs = func(pl []core.PendingLogsEvent) []*types.Log {
   535  			var logs []*types.Log
   536  			for _, l := range pl {
   537  				logs = append(logs, l.Logs...)
   538  			}
   539  			return logs
   540  		}
   541  
   542  		testCases = []struct {
   543  			crit     ethereum.FilterQuery
   544  			expected []*types.Log
   545  			c        chan []*types.Log
   546  			sub      *Subscription
   547  		}{
   548  //全部匹配
   549  			{ethereum.FilterQuery{}, convertLogs(allLogs), nil, nil},
   550  //由于没有匹配的地址而不匹配
   551  			{ethereum.FilterQuery{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}}, []*types.Log{}, nil, nil},
   552  //根据地址匹配日志,忽略主题
   553  			{ethereum.FilterQuery{Addresses: []common.Address{firstAddr}}, append(convertLogs(allLogs[:2]), allLogs[5].Logs[3]), nil, nil},
   554  //由于没有匹配的主题(与地址匹配),因此不匹配
   555  			{ethereum.FilterQuery{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}}, []*types.Log{}, nil, nil},
   556  //根据地址和主题匹配日志
   557  			{ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, append(convertLogs(allLogs[3:5]), allLogs[5].Logs[0]), nil, nil},
   558  //基于多个地址和“或”主题匹配日志
   559  			{ethereum.FilterQuery{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, append(convertLogs(allLogs[2:5]), allLogs[5].Logs[0]), nil, nil},
   560  //对于使用新的***筛选器创建的筛选器,将忽略块号,这些块号将在状态更改时返回与给定条件匹配的所有日志。
   561  			{ethereum.FilterQuery{Addresses: []common.Address{firstAddr}, FromBlock: big.NewInt(2), ToBlock: big.NewInt(3)}, append(convertLogs(allLogs[:2]), allLogs[5].Logs[3]), nil, nil},
   562  //多个挂起的日志,应该只匹配块5中日志中的2个主题
   563  			{ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, fourthTopic}}}, []*types.Log{allLogs[5].Logs[0], allLogs[5].Logs[2]}, nil, nil},
   564  		}
   565  	)
   566  
   567  //创建所有订阅,这将确保在发布事件之前创建所有订阅。
   568  //在速度较慢的计算机上,这可能会导致在以下时间之后创建订阅时丢失事件
   569  //(某些)事件已发布。
   570  	for i := range testCases {
   571  		testCases[i].c = make(chan []*types.Log)
   572  		testCases[i].sub, _ = api.events.SubscribeLogs(testCases[i].crit, testCases[i].c)
   573  	}
   574  
   575  	for n, test := range testCases {
   576  		i := n
   577  		tt := test
   578  		go func() {
   579  			var fetched []*types.Log
   580  		fetchLoop:
   581  			for {
   582  				logs := <-tt.c
   583  				fetched = append(fetched, logs...)
   584  				if len(fetched) >= len(tt.expected) {
   585  					break fetchLoop
   586  				}
   587  			}
   588  
   589  			if len(fetched) != len(tt.expected) {
   590  				panic(fmt.Sprintf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched)))
   591  			}
   592  
   593  			for l := range fetched {
   594  				if fetched[l].Removed {
   595  					panic(fmt.Sprintf("expected log not to be removed for log %d in case %d", l, i))
   596  				}
   597  				if !reflect.DeepEqual(fetched[l], tt.expected[l]) {
   598  					panic(fmt.Sprintf("invalid log on index %d for case %d", l, i))
   599  				}
   600  			}
   601  		}()
   602  	}
   603  
   604  //提高事件
   605  	time.Sleep(1 * time.Second)
   606  //所有日志都是core.pendingLogSevent类型
   607  	for _, l := range allLogs {
   608  		if err := mux.Post(l); err != nil {
   609  			t.Fatal(err)
   610  		}
   611  	}
   612  }
   613