github.com/cryptogateway/go-paymex@v0.0.0-20210204174735-96277fb1e602/les/test_helper.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 // This file contains some shares testing functionality, common to multiple 18 // different files and modules being tested. 19 20 package les 21 22 import ( 23 "context" 24 "crypto/rand" 25 "fmt" 26 "math/big" 27 "sync/atomic" 28 "testing" 29 "time" 30 31 "github.com/cryptogateway/go-paymex/accounts/abi/bind" 32 "github.com/cryptogateway/go-paymex/accounts/abi/bind/backends" 33 "github.com/cryptogateway/go-paymex/common" 34 "github.com/cryptogateway/go-paymex/common/mclock" 35 "github.com/cryptogateway/go-paymex/consensus/ethash" 36 "github.com/cryptogateway/go-paymex/contracts/checkpointoracle/contract" 37 "github.com/cryptogateway/go-paymex/core" 38 "github.com/cryptogateway/go-paymex/core/rawdb" 39 "github.com/cryptogateway/go-paymex/core/types" 40 "github.com/cryptogateway/go-paymex/crypto" 41 "github.com/cryptogateway/go-paymex/eth" 42 "github.com/cryptogateway/go-paymex/ethdb" 43 "github.com/cryptogateway/go-paymex/event" 44 "github.com/cryptogateway/go-paymex/les/checkpointoracle" 45 "github.com/cryptogateway/go-paymex/les/flowcontrol" 46 "github.com/cryptogateway/go-paymex/light" 47 "github.com/cryptogateway/go-paymex/p2p" 48 "github.com/cryptogateway/go-paymex/p2p/enode" 49 "github.com/cryptogateway/go-paymex/p2p/nodestate" 50 "github.com/cryptogateway/go-paymex/params" 51 ) 52 53 var ( 54 bankKey, _ = crypto.GenerateKey() 55 bankAddr = crypto.PubkeyToAddress(bankKey.PublicKey) 56 bankFunds = big.NewInt(1000000000000000000) 57 58 userKey1, _ = crypto.GenerateKey() 59 userKey2, _ = crypto.GenerateKey() 60 userAddr1 = crypto.PubkeyToAddress(userKey1.PublicKey) 61 userAddr2 = crypto.PubkeyToAddress(userKey2.PublicKey) 62 63 testContractAddr common.Address 64 testContractCode = common.Hex2Bytes("606060405260cc8060106000396000f360606040526000357c01000000000000000000000000000000000000000000000000000000009004806360cd2685146041578063c16431b914606b57603f565b005b6055600480803590602001909190505060a9565b6040518082815260200191505060405180910390f35b60886004808035906020019091908035906020019091905050608a565b005b80600060005083606481101560025790900160005b50819055505b5050565b6000600060005082606481101560025790900160005b5054905060c7565b91905056") 65 testContractCodeDeployed = testContractCode[16:] 66 testContractDeployed = uint64(2) 67 68 testEventEmitterCode = common.Hex2Bytes("60606040523415600e57600080fd5b7f57050ab73f6b9ebdd9f76b8d4997793f48cf956e965ee070551b9ca0bb71584e60405160405180910390a160358060476000396000f3006060604052600080fd00a165627a7a723058203f727efcad8b5811f8cb1fc2620ce5e8c63570d697aef968172de296ea3994140029") 69 70 // Checkpoint registrar relative 71 registrarAddr common.Address 72 signerKey, _ = crypto.GenerateKey() 73 signerAddr = crypto.PubkeyToAddress(signerKey.PublicKey) 74 ) 75 76 var ( 77 // The block frequency for creating checkpoint(only used in test) 78 sectionSize = big.NewInt(128) 79 80 // The number of confirmations needed to generate a checkpoint(only used in test). 81 processConfirms = big.NewInt(1) 82 83 // The token bucket buffer limit for testing purpose. 84 testBufLimit = uint64(1000000) 85 86 // The buffer recharging speed for testing purpose. 87 testBufRecharge = uint64(1000) 88 ) 89 90 /* 91 contract test { 92 93 uint256[100] data; 94 95 function Put(uint256 addr, uint256 value) { 96 data[addr] = value; 97 } 98 99 function Get(uint256 addr) constant returns (uint256 value) { 100 return data[addr]; 101 } 102 } 103 */ 104 105 // prepare pre-commits specified number customized blocks into chain. 106 func prepare(n int, backend *backends.SimulatedBackend) { 107 var ( 108 ctx = context.Background() 109 signer = types.HomesteadSigner{} 110 ) 111 for i := 0; i < n; i++ { 112 switch i { 113 case 0: 114 // deploy checkpoint contract 115 auth, _ := bind.NewKeyedTransactorWithChainID(bankKey, big.NewInt(1337)) 116 registrarAddr, _, _, _ = contract.DeployCheckpointOracle(auth, backend, []common.Address{signerAddr}, sectionSize, processConfirms, big.NewInt(1)) 117 // bankUser transfers some ether to user1 118 nonce, _ := backend.PendingNonceAt(ctx, bankAddr) 119 tx, _ := types.SignTx(types.NewTransaction(nonce, userAddr1, big.NewInt(10000), params.TxGas, nil, nil), signer, bankKey) 120 backend.SendTransaction(ctx, tx) 121 case 1: 122 bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr) 123 userNonce1, _ := backend.PendingNonceAt(ctx, userAddr1) 124 125 // bankUser transfers more ether to user1 126 tx1, _ := types.SignTx(types.NewTransaction(bankNonce, userAddr1, big.NewInt(1000), params.TxGas, nil, nil), signer, bankKey) 127 backend.SendTransaction(ctx, tx1) 128 129 // user1 relays ether to user2 130 tx2, _ := types.SignTx(types.NewTransaction(userNonce1, userAddr2, big.NewInt(1000), params.TxGas, nil, nil), signer, userKey1) 131 backend.SendTransaction(ctx, tx2) 132 133 // user1 deploys a test contract 134 tx3, _ := types.SignTx(types.NewContractCreation(userNonce1+1, big.NewInt(0), 200000, big.NewInt(0), testContractCode), signer, userKey1) 135 backend.SendTransaction(ctx, tx3) 136 testContractAddr = crypto.CreateAddress(userAddr1, userNonce1+1) 137 138 // user1 deploys a event contract 139 tx4, _ := types.SignTx(types.NewContractCreation(userNonce1+2, big.NewInt(0), 200000, big.NewInt(0), testEventEmitterCode), signer, userKey1) 140 backend.SendTransaction(ctx, tx4) 141 case 2: 142 // bankUser transfer some ether to signer 143 bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr) 144 tx1, _ := types.SignTx(types.NewTransaction(bankNonce, signerAddr, big.NewInt(1000000000), params.TxGas, nil, nil), signer, bankKey) 145 backend.SendTransaction(ctx, tx1) 146 147 // invoke test contract 148 data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001") 149 tx2, _ := types.SignTx(types.NewTransaction(bankNonce+1, testContractAddr, big.NewInt(0), 100000, nil, data), signer, bankKey) 150 backend.SendTransaction(ctx, tx2) 151 case 3: 152 // invoke test contract 153 bankNonce, _ := backend.PendingNonceAt(ctx, bankAddr) 154 data := common.Hex2Bytes("C16431B900000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002") 155 tx, _ := types.SignTx(types.NewTransaction(bankNonce, testContractAddr, big.NewInt(0), 100000, nil, data), signer, bankKey) 156 backend.SendTransaction(ctx, tx) 157 } 158 backend.Commit() 159 } 160 } 161 162 // testIndexers creates a set of indexers with specified params for testing purpose. 163 func testIndexers(db ethdb.Database, odr light.OdrBackend, config *light.IndexerConfig, disablePruning bool) []*core.ChainIndexer { 164 var indexers [3]*core.ChainIndexer 165 indexers[0] = light.NewChtIndexer(db, odr, config.ChtSize, config.ChtConfirms, disablePruning) 166 indexers[1] = eth.NewBloomIndexer(db, config.BloomSize, config.BloomConfirms) 167 indexers[2] = light.NewBloomTrieIndexer(db, odr, config.BloomSize, config.BloomTrieSize, disablePruning) 168 // make bloomTrieIndexer as a child indexer of bloom indexer. 169 indexers[1].AddChildIndexer(indexers[2]) 170 return indexers[:] 171 } 172 173 func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, indexers []*core.ChainIndexer, db ethdb.Database, peers *serverPeerSet, ulcServers []string, ulcFraction int) *clientHandler { 174 var ( 175 evmux = new(event.TypeMux) 176 engine = ethash.NewFaker() 177 gspec = core.Genesis{ 178 Config: params.AllEthashProtocolChanges, 179 Alloc: core.GenesisAlloc{bankAddr: {Balance: bankFunds}}, 180 GasLimit: 100000000, 181 } 182 oracle *checkpointoracle.CheckpointOracle 183 ) 184 genesis := gspec.MustCommit(db) 185 chain, _ := light.NewLightChain(odr, gspec.Config, engine, nil) 186 if indexers != nil { 187 checkpointConfig := ¶ms.CheckpointOracleConfig{ 188 Address: crypto.CreateAddress(bankAddr, 0), 189 Signers: []common.Address{signerAddr}, 190 Threshold: 1, 191 } 192 getLocal := func(index uint64) params.TrustedCheckpoint { 193 chtIndexer := indexers[0] 194 sectionHead := chtIndexer.SectionHead(index) 195 return params.TrustedCheckpoint{ 196 SectionIndex: index, 197 SectionHead: sectionHead, 198 CHTRoot: light.GetChtRoot(db, index, sectionHead), 199 BloomRoot: light.GetBloomTrieRoot(db, index, sectionHead), 200 } 201 } 202 oracle = checkpointoracle.New(checkpointConfig, getLocal) 203 } 204 client := &LightEthereum{ 205 lesCommons: lesCommons{ 206 genesis: genesis.Hash(), 207 config: ð.Config{LightPeers: 100, NetworkId: NetworkId}, 208 chainConfig: params.AllEthashProtocolChanges, 209 iConfig: light.TestClientIndexerConfig, 210 chainDb: db, 211 oracle: oracle, 212 chainReader: chain, 213 closeCh: make(chan struct{}), 214 }, 215 peers: peers, 216 reqDist: odr.retriever.dist, 217 retriever: odr.retriever, 218 odr: odr, 219 engine: engine, 220 blockchain: chain, 221 eventMux: evmux, 222 } 223 client.handler = newClientHandler(ulcServers, ulcFraction, nil, client) 224 225 if client.oracle != nil { 226 client.oracle.Start(backend) 227 } 228 client.handler.start() 229 return client.handler 230 } 231 232 func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Database, clock mclock.Clock) (*serverHandler, *backends.SimulatedBackend) { 233 var ( 234 gspec = core.Genesis{ 235 Config: params.AllEthashProtocolChanges, 236 Alloc: core.GenesisAlloc{bankAddr: {Balance: bankFunds}}, 237 GasLimit: 100000000, 238 } 239 oracle *checkpointoracle.CheckpointOracle 240 ) 241 genesis := gspec.MustCommit(db) 242 243 // create a simulation backend and pre-commit several customized block to the database. 244 simulation := backends.NewSimulatedBackendWithDatabase(db, gspec.Alloc, 100000000) 245 prepare(blocks, simulation) 246 247 txpoolConfig := core.DefaultTxPoolConfig 248 txpoolConfig.Journal = "" 249 txpool := core.NewTxPool(txpoolConfig, gspec.Config, simulation.Blockchain()) 250 if indexers != nil { 251 checkpointConfig := ¶ms.CheckpointOracleConfig{ 252 Address: crypto.CreateAddress(bankAddr, 0), 253 Signers: []common.Address{signerAddr}, 254 Threshold: 1, 255 } 256 getLocal := func(index uint64) params.TrustedCheckpoint { 257 chtIndexer := indexers[0] 258 sectionHead := chtIndexer.SectionHead(index) 259 return params.TrustedCheckpoint{ 260 SectionIndex: index, 261 SectionHead: sectionHead, 262 CHTRoot: light.GetChtRoot(db, index, sectionHead), 263 BloomRoot: light.GetBloomTrieRoot(db, index, sectionHead), 264 } 265 } 266 oracle = checkpointoracle.New(checkpointConfig, getLocal) 267 } 268 ns := nodestate.NewNodeStateMachine(nil, nil, mclock.System{}, serverSetup) 269 server := &LesServer{ 270 lesCommons: lesCommons{ 271 genesis: genesis.Hash(), 272 config: ð.Config{LightPeers: 100, NetworkId: NetworkId}, 273 chainConfig: params.AllEthashProtocolChanges, 274 iConfig: light.TestServerIndexerConfig, 275 chainDb: db, 276 chainReader: simulation.Blockchain(), 277 oracle: oracle, 278 closeCh: make(chan struct{}), 279 }, 280 ns: ns, 281 broadcaster: newBroadcaster(ns), 282 servingQueue: newServingQueue(int64(time.Millisecond*10), 1), 283 defParams: flowcontrol.ServerParams{ 284 BufLimit: testBufLimit, 285 MinRecharge: testBufRecharge, 286 }, 287 fcManager: flowcontrol.NewClientManager(nil, clock), 288 } 289 server.costTracker, server.minCapacity = newCostTracker(db, server.config) 290 server.costTracker.testCostList = testCostList(0) // Disable flow control mechanism. 291 server.clientPool = newClientPool(ns, db, testBufRecharge, defaultConnectedBias, clock, func(id enode.ID) {}) 292 server.clientPool.setLimits(10000, 10000) // Assign enough capacity for clientpool 293 server.handler = newServerHandler(server, simulation.Blockchain(), db, txpool, func() bool { return true }) 294 if server.oracle != nil { 295 server.oracle.Start(simulation) 296 } 297 server.servingQueue.setThreads(4) 298 ns.Start() 299 server.handler.start() 300 return server.handler, simulation 301 } 302 303 // testPeer is a simulated peer to allow testing direct network calls. 304 type testPeer struct { 305 cpeer *clientPeer 306 speer *serverPeer 307 308 net p2p.MsgReadWriter // Network layer reader/writer to simulate remote messaging 309 app *p2p.MsgPipeRW // Application layer reader/writer to simulate the local side 310 } 311 312 // newTestPeer creates a new peer registered at the given protocol manager. 313 func newTestPeer(t *testing.T, name string, version int, handler *serverHandler, shake bool, testCost uint64) (*testPeer, <-chan error) { 314 // Create a message pipe to communicate through 315 app, net := p2p.MsgPipe() 316 317 // Generate a random id and create the peer 318 var id enode.ID 319 rand.Read(id[:]) 320 peer := newClientPeer(version, NetworkId, p2p.NewPeer(id, name, nil), net) 321 322 // Start the peer on a new thread 323 errCh := make(chan error, 1) 324 go func() { 325 select { 326 case <-handler.closeCh: 327 errCh <- p2p.DiscQuitting 328 case errCh <- handler.handle(peer): 329 } 330 }() 331 tp := &testPeer{ 332 app: app, 333 net: net, 334 cpeer: peer, 335 } 336 // Execute any implicitly requested handshakes and return 337 if shake { 338 // Customize the cost table if required. 339 if testCost != 0 { 340 handler.server.costTracker.testCostList = testCostList(testCost) 341 } 342 var ( 343 genesis = handler.blockchain.Genesis() 344 head = handler.blockchain.CurrentHeader() 345 td = handler.blockchain.GetTd(head.Hash(), head.Number.Uint64()) 346 ) 347 tp.handshake(t, td, head.Hash(), head.Number.Uint64(), genesis.Hash(), testCostList(testCost)) 348 } 349 return tp, errCh 350 } 351 352 // close terminates the local side of the peer, notifying the remote protocol 353 // manager of termination. 354 func (p *testPeer) close() { 355 p.app.Close() 356 } 357 358 func newTestPeerPair(name string, version int, server *serverHandler, client *clientHandler) (*testPeer, *testPeer, error) { 359 // Create a message pipe to communicate through 360 app, net := p2p.MsgPipe() 361 362 // Generate a random id and create the peer 363 var id enode.ID 364 rand.Read(id[:]) 365 366 peer1 := newClientPeer(version, NetworkId, p2p.NewPeer(id, name, nil), net) 367 peer2 := newServerPeer(version, NetworkId, false, p2p.NewPeer(id, name, nil), app) 368 369 // Start the peer on a new thread 370 errc1 := make(chan error, 1) 371 errc2 := make(chan error, 1) 372 go func() { 373 select { 374 case <-server.closeCh: 375 errc1 <- p2p.DiscQuitting 376 case errc1 <- server.handle(peer1): 377 } 378 }() 379 go func() { 380 select { 381 case <-client.closeCh: 382 errc2 <- p2p.DiscQuitting 383 case errc2 <- client.handle(peer2): 384 } 385 }() 386 // Ensure the connection is established or exits when any error occurs 387 for { 388 select { 389 case err := <-errc1: 390 return nil, nil, fmt.Errorf("Failed to establish protocol connection %v", err) 391 case err := <-errc2: 392 return nil, nil, fmt.Errorf("Failed to establish protocol connection %v", err) 393 default: 394 } 395 if atomic.LoadUint32(&peer1.serving) == 1 && atomic.LoadUint32(&peer2.serving) == 1 { 396 break 397 } 398 time.Sleep(50 * time.Millisecond) 399 } 400 return &testPeer{cpeer: peer1, net: net, app: app}, &testPeer{speer: peer2, net: app, app: net}, nil 401 } 402 403 // handshake simulates a trivial handshake that expects the same state from the 404 // remote side as we are simulating locally. 405 func (p *testPeer) handshake(t *testing.T, td *big.Int, head common.Hash, headNum uint64, genesis common.Hash, costList RequestCostList) { 406 var expList keyValueList 407 expList = expList.add("protocolVersion", uint64(p.cpeer.version)) 408 expList = expList.add("networkId", uint64(NetworkId)) 409 expList = expList.add("headTd", td) 410 expList = expList.add("headHash", head) 411 expList = expList.add("headNum", headNum) 412 expList = expList.add("genesisHash", genesis) 413 sendList := make(keyValueList, len(expList)) 414 copy(sendList, expList) 415 expList = expList.add("serveHeaders", nil) 416 expList = expList.add("serveChainSince", uint64(0)) 417 expList = expList.add("serveStateSince", uint64(0)) 418 expList = expList.add("serveRecentState", uint64(core.TriesInMemory-4)) 419 expList = expList.add("txRelay", nil) 420 expList = expList.add("flowControl/BL", testBufLimit) 421 expList = expList.add("flowControl/MRR", testBufRecharge) 422 expList = expList.add("flowControl/MRC", costList) 423 424 if err := p2p.ExpectMsg(p.app, StatusMsg, expList); err != nil { 425 t.Fatalf("status recv: %v", err) 426 } 427 if err := p2p.Send(p.app, StatusMsg, sendList); err != nil { 428 t.Fatalf("status send: %v", err) 429 } 430 p.cpeer.fcParams = flowcontrol.ServerParams{ 431 BufLimit: testBufLimit, 432 MinRecharge: testBufRecharge, 433 } 434 } 435 436 type indexerCallback func(*core.ChainIndexer, *core.ChainIndexer, *core.ChainIndexer) 437 438 // testClient represents a client for testing with necessary auxiliary fields. 439 type testClient struct { 440 clock mclock.Clock 441 db ethdb.Database 442 peer *testPeer 443 handler *clientHandler 444 445 chtIndexer *core.ChainIndexer 446 bloomIndexer *core.ChainIndexer 447 bloomTrieIndexer *core.ChainIndexer 448 } 449 450 // testServer represents a server for testing with necessary auxiliary fields. 451 type testServer struct { 452 clock mclock.Clock 453 backend *backends.SimulatedBackend 454 db ethdb.Database 455 peer *testPeer 456 handler *serverHandler 457 458 chtIndexer *core.ChainIndexer 459 bloomIndexer *core.ChainIndexer 460 bloomTrieIndexer *core.ChainIndexer 461 } 462 463 func newServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallback, simClock bool, newPeer bool, testCost uint64) (*testServer, func()) { 464 db := rawdb.NewMemoryDatabase() 465 indexers := testIndexers(db, nil, light.TestServerIndexerConfig, true) 466 467 var clock mclock.Clock = &mclock.System{} 468 if simClock { 469 clock = &mclock.Simulated{} 470 } 471 handler, b := newTestServerHandler(blocks, indexers, db, clock) 472 473 var peer *testPeer 474 if newPeer { 475 peer, _ = newTestPeer(t, "peer", protocol, handler, true, testCost) 476 } 477 478 cIndexer, bIndexer, btIndexer := indexers[0], indexers[1], indexers[2] 479 cIndexer.Start(handler.blockchain) 480 bIndexer.Start(handler.blockchain) 481 482 // Wait until indexers generate enough index data. 483 if callback != nil { 484 callback(cIndexer, bIndexer, btIndexer) 485 } 486 server := &testServer{ 487 clock: clock, 488 backend: b, 489 db: db, 490 peer: peer, 491 handler: handler, 492 chtIndexer: cIndexer, 493 bloomIndexer: bIndexer, 494 bloomTrieIndexer: btIndexer, 495 } 496 teardown := func() { 497 if newPeer { 498 peer.close() 499 peer.cpeer.close() 500 b.Close() 501 } 502 cIndexer.Close() 503 bIndexer.Close() 504 } 505 return server, teardown 506 } 507 508 func newClientServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallback, ulcServers []string, ulcFraction int, simClock bool, connect bool, disablePruning bool) (*testServer, *testClient, func()) { 509 sdb, cdb := rawdb.NewMemoryDatabase(), rawdb.NewMemoryDatabase() 510 speers := newServerPeerSet() 511 512 var clock mclock.Clock = &mclock.System{} 513 if simClock { 514 clock = &mclock.Simulated{} 515 } 516 dist := newRequestDistributor(speers, clock) 517 rm := newRetrieveManager(speers, dist, func() time.Duration { return time.Millisecond * 500 }) 518 odr := NewLesOdr(cdb, light.TestClientIndexerConfig, rm) 519 520 sindexers := testIndexers(sdb, nil, light.TestServerIndexerConfig, true) 521 cIndexers := testIndexers(cdb, odr, light.TestClientIndexerConfig, disablePruning) 522 523 scIndexer, sbIndexer, sbtIndexer := sindexers[0], sindexers[1], sindexers[2] 524 ccIndexer, cbIndexer, cbtIndexer := cIndexers[0], cIndexers[1], cIndexers[2] 525 odr.SetIndexers(ccIndexer, cbIndexer, cbtIndexer) 526 527 server, b := newTestServerHandler(blocks, sindexers, sdb, clock) 528 client := newTestClientHandler(b, odr, cIndexers, cdb, speers, ulcServers, ulcFraction) 529 530 scIndexer.Start(server.blockchain) 531 sbIndexer.Start(server.blockchain) 532 ccIndexer.Start(client.backend.blockchain) 533 cbIndexer.Start(client.backend.blockchain) 534 535 if callback != nil { 536 callback(scIndexer, sbIndexer, sbtIndexer) 537 } 538 var ( 539 err error 540 speer, cpeer *testPeer 541 ) 542 if connect { 543 done := make(chan struct{}) 544 client.syncEnd = func(_ *types.Header) { close(done) } 545 cpeer, speer, err = newTestPeerPair("peer", protocol, server, client) 546 if err != nil { 547 t.Fatalf("Failed to connect testing peers %v", err) 548 } 549 select { 550 case <-done: 551 case <-time.After(10 * time.Second): 552 t.Fatal("test peer did not connect and sync within 3s") 553 } 554 } 555 s := &testServer{ 556 clock: clock, 557 backend: b, 558 db: sdb, 559 peer: cpeer, 560 handler: server, 561 chtIndexer: scIndexer, 562 bloomIndexer: sbIndexer, 563 bloomTrieIndexer: sbtIndexer, 564 } 565 c := &testClient{ 566 clock: clock, 567 db: cdb, 568 peer: speer, 569 handler: client, 570 chtIndexer: ccIndexer, 571 bloomIndexer: cbIndexer, 572 bloomTrieIndexer: cbtIndexer, 573 } 574 teardown := func() { 575 if connect { 576 speer.close() 577 cpeer.close() 578 cpeer.cpeer.close() 579 speer.speer.close() 580 } 581 ccIndexer.Close() 582 cbIndexer.Close() 583 scIndexer.Close() 584 sbIndexer.Close() 585 b.Close() 586 } 587 return s, c, teardown 588 }