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 }