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