github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/eth/filters/filter_system_test.go (about)

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