github.com/Finschia/ostracon@v1.1.5/p2p/pex/pex_reactor_test.go (about) 1 package pex 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "os" 7 "path/filepath" 8 "testing" 9 "time" 10 11 "github.com/gogo/protobuf/proto" 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 tmp2p "github.com/tendermint/tendermint/proto/tendermint/p2p" 16 17 "github.com/Finschia/ostracon/config" 18 "github.com/Finschia/ostracon/libs/log" 19 "github.com/Finschia/ostracon/p2p" 20 "github.com/Finschia/ostracon/p2p/mock" 21 ) 22 23 var cfg *config.P2PConfig 24 25 func init() { 26 cfg = config.DefaultP2PConfig() 27 cfg.PexReactor = true 28 cfg.AllowDuplicateIP = true 29 } 30 31 func TestPEXReactorBasic(t *testing.T) { 32 r, book := createReactor(&ReactorConfig{}) 33 defer teardownReactor(book) 34 35 assert.NotNil(t, r) 36 assert.NotEmpty(t, r.GetChannels()) 37 } 38 39 func TestPEXReactorAddRemovePeer(t *testing.T) { 40 r, book := createReactor(&ReactorConfig{}) 41 defer teardownReactor(book) 42 43 size := book.Size() 44 peer := p2p.CreateRandomPeer(false) 45 46 r.AddPeer(peer) 47 assert.Equal(t, size+1, book.Size()) 48 49 r.RemovePeer(peer, "peer not available") 50 51 outboundPeer := p2p.CreateRandomPeer(true) 52 53 r.AddPeer(outboundPeer) 54 assert.Equal(t, size+1, book.Size(), "outbound peers should not be added to the address book") 55 56 r.RemovePeer(outboundPeer, "peer not available") 57 } 58 59 // --- FAIL: TestPEXReactorRunning (11.10s) 60 // 61 // pex_reactor_test.go:411: expected all switches to be connected to at 62 // least one peer (switches: 0 => {outbound: 1, inbound: 0}, 1 => 63 // {outbound: 0, inbound: 1}, 2 => {outbound: 0, inbound: 0}, ) 64 // 65 // EXPLANATION: peers are getting rejected because in switch#addPeer we check 66 // if any peer (who we already connected to) has the same IP. Even though local 67 // peers have different IP addresses, they all have the same underlying remote 68 // IP: 127.0.0.1. 69 func TestPEXReactorRunning(t *testing.T) { 70 N := 3 71 switches := make([]*p2p.Switch, N) 72 73 // directory to store address books 74 dir, err := os.MkdirTemp("", "pex_reactor") 75 require.Nil(t, err) 76 defer os.RemoveAll(dir) 77 78 books := make([]AddrBook, N) 79 logger := log.TestingLogger() 80 81 // create switches 82 for i := 0; i < N; i++ { 83 switches[i] = p2p.MakeSwitch(cfg, i, "testing", "123.123.123", func(i int, sw *p2p.Switch, 84 config *config.P2PConfig) *p2p.Switch { 85 books[i] = NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", i)), false) 86 books[i].SetLogger(logger.With("pex", i)) 87 sw.SetAddrBook(books[i]) 88 89 sw.SetLogger(logger.With("pex", i)) 90 91 r := NewReactor(books[i], config.RecvAsync, &ReactorConfig{}) 92 r.SetLogger(logger.With("pex", i)) 93 r.SetEnsurePeersPeriod(250 * time.Millisecond) 94 sw.AddReactor("pex", r) 95 96 return sw 97 }) 98 } 99 100 addOtherNodeAddrToAddrBook := func(switchIndex, otherSwitchIndex int) { 101 addr := switches[otherSwitchIndex].NetAddress() 102 err := books[switchIndex].AddAddress(addr, addr) 103 require.NoError(t, err) 104 } 105 106 addOtherNodeAddrToAddrBook(0, 1) 107 addOtherNodeAddrToAddrBook(1, 0) 108 addOtherNodeAddrToAddrBook(2, 1) 109 110 for _, sw := range switches { 111 err := sw.Start() // start switch and reactors 112 require.Nil(t, err) 113 } 114 115 assertPeersWithTimeout(t, switches, 10*time.Millisecond, 10*time.Second, N-1) 116 117 // stop them 118 for _, s := range switches { 119 err := s.Stop() 120 require.NoError(t, err) 121 } 122 } 123 124 func TestPEXReactorReceive(t *testing.T) { 125 r, book := createReactor(&ReactorConfig{}) 126 defer teardownReactor(book) 127 128 peer := p2p.CreateRandomPeer(false) 129 130 // we have to send a request to receive responses 131 r.RequestAddrs(peer) 132 133 size := book.Size() 134 msg := &tmp2p.PexAddrs{Addrs: []tmp2p.NetAddress{peer.SocketAddr().ToProto()}} 135 r.ReceiveEnvelope(p2p.Envelope{ChannelID: PexChannel, Src: peer, Message: msg}) 136 assert.Equal(t, size+1, book.Size()) 137 138 r.ReceiveEnvelope(p2p.Envelope{ChannelID: PexChannel, Src: peer, Message: &tmp2p.PexRequest{}}) 139 } 140 141 func TestPEXReactorRequestMessageAbuse(t *testing.T) { 142 r, book := createReactor(&ReactorConfig{}) 143 defer teardownReactor(book) 144 145 sw := createSwitchAndAddReactors(r) 146 sw.SetAddrBook(book) 147 148 peer := mock.NewPeer(nil) 149 peerAddr := peer.SocketAddr() 150 p2p.AddPeerToSwitchPeerSet(sw, peer) 151 assert.True(t, sw.Peers().Has(peer.ID())) 152 err := book.AddAddress(peerAddr, peerAddr) 153 require.NoError(t, err) 154 require.True(t, book.HasAddress(peerAddr)) 155 156 id := string(peer.ID()) 157 158 // first time creates the entry 159 r.ReceiveEnvelope(p2p.Envelope{ChannelID: PexChannel, Src: peer, Message: &tmp2p.PexRequest{}}) 160 assert.True(t, r.lastReceivedRequests.Has(id)) 161 assert.True(t, sw.Peers().Has(peer.ID())) 162 163 // next time sets the last time value 164 r.ReceiveEnvelope(p2p.Envelope{ChannelID: PexChannel, Src: peer, Message: &tmp2p.PexRequest{}}) 165 assert.True(t, r.lastReceivedRequests.Has(id)) 166 assert.True(t, sw.Peers().Has(peer.ID())) 167 168 // third time is too many too soon - peer is removed 169 r.ReceiveEnvelope(p2p.Envelope{ChannelID: PexChannel, Src: peer, Message: &tmp2p.PexRequest{}}) 170 assert.False(t, r.lastReceivedRequests.Has(id)) 171 assert.False(t, sw.Peers().Has(peer.ID())) 172 assert.True(t, book.IsBanned(peerAddr)) 173 } 174 175 func TestPEXReactorAddrsMessageAbuse(t *testing.T) { 176 r, book := createReactor(&ReactorConfig{}) 177 defer teardownReactor(book) 178 179 sw := createSwitchAndAddReactors(r) 180 sw.SetAddrBook(book) 181 182 peer := mock.NewPeer(nil) 183 p2p.AddPeerToSwitchPeerSet(sw, peer) 184 assert.True(t, sw.Peers().Has(peer.ID())) 185 186 id := string(peer.ID()) 187 188 // request addrs from the peer 189 r.RequestAddrs(peer) 190 assert.True(t, r.requestsSent.Has(id)) 191 assert.True(t, sw.Peers().Has(peer.ID())) 192 193 msg := &tmp2p.PexAddrs{Addrs: []tmp2p.NetAddress{peer.SocketAddr().ToProto()}} 194 195 // receive some addrs. should clear the request 196 r.ReceiveEnvelope(p2p.Envelope{ChannelID: PexChannel, Src: peer, Message: msg}) 197 assert.False(t, r.requestsSent.Has(id)) 198 assert.True(t, sw.Peers().Has(peer.ID())) 199 200 // receiving more unsolicited addrs causes a disconnect and ban 201 r.ReceiveEnvelope(p2p.Envelope{ChannelID: PexChannel, Src: peer, Message: msg}) 202 assert.False(t, sw.Peers().Has(peer.ID())) 203 assert.True(t, book.IsBanned(peer.SocketAddr())) 204 } 205 206 func TestCheckSeeds(t *testing.T) { 207 // directory to store address books 208 dir, err := os.MkdirTemp("", "pex_reactor") 209 require.Nil(t, err) 210 defer os.RemoveAll(dir) 211 212 // 1. test creating peer with no seeds works 213 peerSwitch := testCreateDefaultPeer(dir, 0) 214 require.Nil(t, peerSwitch.Start()) 215 peerSwitch.Stop() // nolint:errcheck // ignore for tests 216 217 // 2. create seed 218 seed := testCreateSeed(dir, 1, []*p2p.NetAddress{}, []*p2p.NetAddress{}) 219 220 // 3. test create peer with online seed works 221 peerSwitch = testCreatePeerWithSeed(dir, 2, seed) 222 require.Nil(t, peerSwitch.Start()) 223 peerSwitch.Stop() // nolint:errcheck // ignore for tests 224 225 // 4. test create peer with all seeds having unresolvable DNS fails 226 badPeerConfig := &ReactorConfig{ 227 Seeds: []string{ 228 "ed3dfd27bfc4af18f67a49862f04cc100696e84d@bad.network.addr:26657", 229 "d824b13cb5d40fa1d8a614e089357c7eff31b670@anotherbad.network.addr:26657", 230 }, 231 } 232 peerSwitch = testCreatePeerWithConfig(dir, 2, badPeerConfig) 233 require.Error(t, peerSwitch.Start()) 234 peerSwitch.Stop() // nolint:errcheck // ignore for tests 235 236 // 5. test create peer with one good seed address succeeds 237 badPeerConfig = &ReactorConfig{ 238 Seeds: []string{ 239 "ed3dfd27bfc4af18f67a49862f04cc100696e84d@bad.network.addr:26657", 240 "d824b13cb5d40fa1d8a614e089357c7eff31b670@anotherbad.network.addr:26657", 241 seed.NetAddress().String(), 242 }, 243 } 244 peerSwitch = testCreatePeerWithConfig(dir, 2, badPeerConfig) 245 require.Nil(t, peerSwitch.Start()) 246 peerSwitch.Stop() // nolint:errcheck // ignore for tests 247 } 248 249 func TestPEXReactorUsesSeedsIfNeeded(t *testing.T) { 250 // directory to store address books 251 dir, err := os.MkdirTemp("", "pex_reactor") 252 require.Nil(t, err) 253 defer os.RemoveAll(dir) 254 255 // 1. create seed 256 seed := testCreateSeed(dir, 0, []*p2p.NetAddress{}, []*p2p.NetAddress{}) 257 require.Nil(t, seed.Start()) 258 defer seed.Stop() // nolint:errcheck // ignore for tests 259 260 // 2. create usual peer with only seed configured. 261 peer := testCreatePeerWithSeed(dir, 1, seed) 262 require.Nil(t, peer.Start()) 263 defer peer.Stop() // nolint:errcheck // ignore for tests 264 265 // 3. check that the peer connects to seed immediately 266 assertPeersWithTimeout(t, []*p2p.Switch{peer}, 10*time.Millisecond, 3*time.Second, 1) 267 } 268 269 func TestConnectionSpeedForPeerReceivedFromSeed(t *testing.T) { 270 // directory to store address books 271 dir, err := os.MkdirTemp("", "pex_reactor") 272 require.Nil(t, err) 273 defer os.RemoveAll(dir) 274 275 // 1. create peer 276 peerSwitch := testCreateDefaultPeer(dir, 1) 277 require.Nil(t, peerSwitch.Start()) 278 defer peerSwitch.Stop() // nolint:errcheck // ignore for tests 279 280 // 2. Create seed which knows about the peer 281 peerAddr := peerSwitch.NetAddress() 282 seed := testCreateSeed(dir, 2, []*p2p.NetAddress{peerAddr}, []*p2p.NetAddress{peerAddr}) 283 require.Nil(t, seed.Start()) 284 defer seed.Stop() // nolint:errcheck // ignore for tests 285 286 // 3. create another peer with only seed configured. 287 secondPeer := testCreatePeerWithSeed(dir, 3, seed) 288 require.Nil(t, secondPeer.Start()) 289 defer secondPeer.Stop() // nolint:errcheck // ignore for tests 290 291 // 4. check that the second peer connects to seed immediately 292 assertPeersWithTimeout(t, []*p2p.Switch{secondPeer}, 10*time.Millisecond, 3*time.Second, 1) 293 294 // 5. check that the second peer connects to the first peer immediately 295 assertPeersWithTimeout(t, []*p2p.Switch{secondPeer}, 10*time.Millisecond, 1*time.Second, 2) 296 } 297 298 func TestPEXReactorSeedMode(t *testing.T) { 299 // directory to store address books 300 dir, err := os.MkdirTemp("", "pex_reactor") 301 require.Nil(t, err) 302 defer os.RemoveAll(dir) 303 304 pexRConfig := &ReactorConfig{SeedMode: true, SeedDisconnectWaitPeriod: 10 * time.Millisecond} 305 pexR, book := createReactor(pexRConfig) 306 defer teardownReactor(book) 307 308 sw := createSwitchAndAddReactors(pexR) 309 sw.SetAddrBook(book) 310 err = sw.Start() 311 require.NoError(t, err) 312 defer sw.Stop() // nolint:errcheck // ignore for tests 313 314 assert.Zero(t, sw.Peers().Size()) 315 316 peerSwitch := testCreateDefaultPeer(dir, 1) 317 require.NoError(t, peerSwitch.Start()) 318 defer peerSwitch.Stop() // nolint:errcheck // ignore for tests 319 320 // 1. Test crawlPeers dials the peer 321 pexR.crawlPeers([]*p2p.NetAddress{peerSwitch.NetAddress()}) 322 assert.Equal(t, 1, sw.Peers().Size()) 323 assert.True(t, sw.Peers().Has(peerSwitch.NodeInfo().ID())) 324 325 // 2. attemptDisconnects should not disconnect because of wait period 326 pexR.attemptDisconnects() 327 assert.Equal(t, 1, sw.Peers().Size()) 328 329 // sleep for SeedDisconnectWaitPeriod 330 time.Sleep(pexRConfig.SeedDisconnectWaitPeriod + 1*time.Millisecond) 331 332 // 3. attemptDisconnects should disconnect after wait period 333 pexR.attemptDisconnects() 334 assert.Equal(t, 0, sw.Peers().Size()) 335 } 336 337 func TestPEXReactorDoesNotDisconnectFromPersistentPeerInSeedMode(t *testing.T) { 338 // directory to store address books 339 dir, err := os.MkdirTemp("", "pex_reactor") 340 require.Nil(t, err) 341 defer os.RemoveAll(dir) 342 343 pexRConfig := &ReactorConfig{SeedMode: true, SeedDisconnectWaitPeriod: 1 * time.Millisecond} 344 pexR, book := createReactor(pexRConfig) 345 defer teardownReactor(book) 346 347 sw := createSwitchAndAddReactors(pexR) 348 sw.SetAddrBook(book) 349 err = sw.Start() 350 require.NoError(t, err) 351 defer sw.Stop() // nolint:errcheck // ignore for tests 352 353 assert.Zero(t, sw.Peers().Size()) 354 355 peerSwitch := testCreateDefaultPeer(dir, 1) 356 require.NoError(t, peerSwitch.Start()) 357 defer peerSwitch.Stop() // nolint:errcheck // ignore for tests 358 359 err = sw.AddPersistentPeers([]string{peerSwitch.NetAddress().String()}) 360 require.NoError(t, err) 361 362 // 1. Test crawlPeers dials the peer 363 pexR.crawlPeers([]*p2p.NetAddress{peerSwitch.NetAddress()}) 364 assert.Equal(t, 1, sw.Peers().Size()) 365 assert.True(t, sw.Peers().Has(peerSwitch.NodeInfo().ID())) 366 367 // sleep for SeedDisconnectWaitPeriod 368 time.Sleep(pexRConfig.SeedDisconnectWaitPeriod + 1*time.Millisecond) 369 370 // 2. attemptDisconnects should not disconnect because the peer is persistent 371 pexR.attemptDisconnects() 372 assert.Equal(t, 1, sw.Peers().Size()) 373 } 374 375 func TestPEXReactorDialsPeerUpToMaxAttemptsInSeedMode(t *testing.T) { 376 // directory to store address books 377 dir, err := os.MkdirTemp("", "pex_reactor") 378 require.Nil(t, err) 379 defer os.RemoveAll(dir) 380 381 pexR, book := createReactor(&ReactorConfig{SeedMode: true}) 382 defer teardownReactor(book) 383 384 sw := createSwitchAndAddReactors(pexR) 385 sw.SetAddrBook(book) 386 // No need to start sw since crawlPeers is called manually here. 387 388 peer := mock.NewPeer(nil) 389 addr := peer.SocketAddr() 390 391 err = book.AddAddress(addr, addr) 392 require.NoError(t, err) 393 394 assert.True(t, book.HasAddress(addr)) 395 396 // imitate maxAttemptsToDial reached 397 pexR.attemptsToDial.Store(addr.DialString(), _attemptsToDial{maxAttemptsToDial + 1, time.Now()}) 398 pexR.crawlPeers([]*p2p.NetAddress{addr}) 399 400 assert.False(t, book.HasAddress(addr)) 401 } 402 403 // connect a peer to a seed, wait a bit, then stop it. 404 // this should give it time to request addrs and for the seed 405 // to call FlushStop, and allows us to test calling Stop concurrently 406 // with FlushStop. Before a fix, this non-deterministically reproduced 407 // https://github.com/tendermint/tendermint/issues/3231. 408 func TestPEXReactorSeedModeFlushStop(t *testing.T) { 409 N := 2 410 switches := make([]*p2p.Switch, N) 411 412 // directory to store address books 413 dir, err := os.MkdirTemp("", "pex_reactor") 414 require.Nil(t, err) 415 defer os.RemoveAll(dir) 416 417 books := make([]AddrBook, N) 418 logger := log.TestingLogger() 419 420 // create switches 421 for i := 0; i < N; i++ { 422 switches[i] = p2p.MakeSwitch(cfg, i, "testing", "123.123.123", func(i int, sw *p2p.Switch, 423 config *config.P2PConfig) *p2p.Switch { 424 books[i] = NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", i)), false) 425 books[i].SetLogger(logger.With("pex", i)) 426 sw.SetAddrBook(books[i]) 427 428 sw.SetLogger(logger.With("pex", i)) 429 430 pexConfig := &ReactorConfig{} 431 if i == 0 { 432 // first one is a seed node 433 pexConfig = &ReactorConfig{SeedMode: true} 434 } 435 r := NewReactor(books[i], config.RecvAsync, pexConfig) 436 r.SetLogger(logger.With("pex", i)) 437 r.SetEnsurePeersPeriod(250 * time.Millisecond) 438 sw.AddReactor("pex", r) 439 440 return sw 441 }) 442 } 443 444 for _, sw := range switches { 445 err := sw.Start() // start switch and reactors 446 require.Nil(t, err) 447 } 448 449 reactor := switches[0].Reactors()["pex"].(*Reactor) 450 peerID := switches[1].NodeInfo().ID() 451 452 err = switches[1].DialPeerWithAddress(switches[0].NetAddress()) 453 assert.NoError(t, err) 454 455 // sleep up to a second while waiting for the peer to send us a message. 456 // this isn't perfect since it's possible the peer sends us a msg and we FlushStop 457 // before this loop catches it. but non-deterministically it works pretty well. 458 for i := 0; i < 1000; i++ { 459 v := reactor.lastReceivedRequests.Get(string(peerID)) 460 if v != nil { 461 break 462 } 463 time.Sleep(time.Millisecond) 464 } 465 466 // by now the FlushStop should have happened. Try stopping the peer. 467 // it should be safe to do this. 468 peers := switches[0].Peers().List() 469 for _, peer := range peers { 470 err := peer.Stop() 471 require.NoError(t, err) 472 } 473 474 // stop the switches 475 for _, s := range switches { 476 err := s.Stop() 477 require.NoError(t, err) 478 } 479 } 480 481 func TestPEXReactorDoesNotAddPrivatePeersToAddrBook(t *testing.T) { 482 peer := p2p.CreateRandomPeer(false) 483 484 pexR, book := createReactor(&ReactorConfig{}) 485 book.AddPrivateIDs([]string{string(peer.NodeInfo().ID())}) 486 defer teardownReactor(book) 487 488 // we have to send a request to receive responses 489 pexR.RequestAddrs(peer) 490 491 size := book.Size() 492 msg := &tmp2p.PexAddrs{Addrs: []tmp2p.NetAddress{peer.SocketAddr().ToProto()}} 493 pexR.ReceiveEnvelope(p2p.Envelope{ 494 ChannelID: PexChannel, 495 Src: peer, 496 Message: msg, 497 }) 498 assert.Equal(t, size, book.Size()) 499 500 pexR.AddPeer(peer) 501 assert.Equal(t, size, book.Size()) 502 } 503 504 func TestLegacyReactorReceiveBasic(t *testing.T) { 505 pexR, _ := createReactor(&ReactorConfig{}) 506 peer := p2p.CreateRandomPeer(false) 507 508 pexR.InitPeer(peer) 509 pexR.AddPeer(peer) 510 m := &tmp2p.PexAddrs{} 511 wm := m.Wrap() 512 msg, err := proto.Marshal(wm) 513 assert.NoError(t, err) 514 515 assert.NotPanics(t, func() { 516 pexR.Receive(PexChannel, peer, msg) 517 }) 518 } 519 520 func TestPEXReactorDialPeer(t *testing.T) { 521 pexR, book := createReactor(&ReactorConfig{}) 522 defer teardownReactor(book) 523 524 sw := createSwitchAndAddReactors(pexR) 525 sw.SetAddrBook(book) 526 527 peer := mock.NewPeer(nil) 528 addr := peer.SocketAddr() 529 530 assert.Equal(t, 0, pexR.AttemptsToDial(addr)) 531 532 // 1st unsuccessful attempt 533 err := pexR.dialPeer(addr) 534 require.Error(t, err) 535 536 assert.Equal(t, 1, pexR.AttemptsToDial(addr)) 537 538 // 2nd unsuccessful attempt 539 err = pexR.dialPeer(addr) 540 require.Error(t, err) 541 542 // must be skipped because it is too early 543 assert.Equal(t, 1, pexR.AttemptsToDial(addr)) 544 545 if !testing.Short() { 546 time.Sleep(3 * time.Second) 547 548 // 3rd attempt 549 err = pexR.dialPeer(addr) 550 require.Error(t, err) 551 552 assert.Equal(t, 2, pexR.AttemptsToDial(addr)) 553 } 554 } 555 556 func assertPeersWithTimeout( 557 t *testing.T, 558 switches []*p2p.Switch, 559 checkPeriod, timeout time.Duration, 560 nPeers int, 561 ) { 562 var ( 563 ticker = time.NewTicker(checkPeriod) 564 remaining = timeout 565 ) 566 567 for { 568 select { 569 case <-ticker.C: 570 // check peers are connected 571 allGood := true 572 for _, s := range switches { 573 outbound, inbound, _ := s.NumPeers() 574 if outbound+inbound < nPeers { 575 allGood = false 576 break 577 } 578 } 579 remaining -= checkPeriod 580 if remaining < 0 { 581 remaining = 0 582 } 583 if allGood { 584 return 585 } 586 case <-time.After(remaining): 587 numPeersStr := "" 588 for i, s := range switches { 589 outbound, inbound, _ := s.NumPeers() 590 numPeersStr += fmt.Sprintf("%d => {outbound: %d, inbound: %d}, ", i, outbound, inbound) 591 } 592 t.Errorf( 593 "expected all switches to be connected to at least %d peer(s) (switches: %s)", 594 nPeers, numPeersStr, 595 ) 596 return 597 } 598 } 599 } 600 601 // Creates a peer with the provided config 602 func testCreatePeerWithConfig(dir string, id int, pexConfig *ReactorConfig) *p2p.Switch { 603 peer := p2p.MakeSwitch( 604 cfg, 605 id, 606 "127.0.0.1", 607 "123.123.123", 608 func(i int, sw *p2p.Switch, config *config.P2PConfig) *p2p.Switch { 609 book := NewAddrBook(filepath.Join(dir, fmt.Sprintf("addrbook%d.json", id)), false) 610 book.SetLogger(log.TestingLogger()) 611 sw.SetAddrBook(book) 612 613 sw.SetLogger(log.TestingLogger()) 614 615 r := NewReactor( 616 book, 617 config.RecvAsync, 618 pexConfig, 619 ) 620 r.SetLogger(log.TestingLogger()) 621 sw.AddReactor("pex", r) 622 return sw 623 }, 624 ) 625 return peer 626 } 627 628 // Creates a peer with the default config 629 func testCreateDefaultPeer(dir string, id int) *p2p.Switch { 630 return testCreatePeerWithConfig(dir, id, &ReactorConfig{RecvBufSize: cfg.PexRecvBufSize}) 631 } 632 633 // Creates a seed which knows about the provided addresses / source address pairs. 634 // Starting and stopping the seed is left to the caller 635 func testCreateSeed(dir string, id int, knownAddrs, srcAddrs []*p2p.NetAddress) *p2p.Switch { 636 seed := p2p.MakeSwitch( 637 cfg, 638 id, 639 "127.0.0.1", 640 "123.123.123", 641 func(i int, sw *p2p.Switch, config *config.P2PConfig) *p2p.Switch { 642 book := NewAddrBook(filepath.Join(dir, "addrbookSeed.json"), false) 643 book.SetLogger(log.TestingLogger()) 644 for j := 0; j < len(knownAddrs); j++ { 645 book.AddAddress(knownAddrs[j], srcAddrs[j]) // nolint:errcheck // ignore for tests 646 book.MarkGood(knownAddrs[j].ID) 647 } 648 sw.SetAddrBook(book) 649 650 sw.SetLogger(log.TestingLogger()) 651 652 r := NewReactor(book, config.RecvAsync, &ReactorConfig{RecvBufSize: cfg.PexRecvBufSize}) 653 r.SetLogger(log.TestingLogger()) 654 sw.AddReactor("pex", r) 655 return sw 656 }, 657 ) 658 return seed 659 } 660 661 // Creates a peer which knows about the provided seed. 662 // Starting and stopping the peer is left to the caller 663 func testCreatePeerWithSeed(dir string, id int, seed *p2p.Switch) *p2p.Switch { 664 conf := &ReactorConfig{ 665 Seeds: []string{seed.NetAddress().String()}, 666 RecvBufSize: cfg.PexRecvBufSize, 667 } 668 return testCreatePeerWithConfig(dir, id, conf) 669 } 670 671 func createReactor(conf *ReactorConfig) (r *Reactor, book AddrBook) { 672 // directory to store address book 673 dir, err := os.MkdirTemp("", "pex_reactor") 674 if err != nil { 675 panic(err) 676 } 677 book = NewAddrBook(filepath.Join(dir, "addrbook.json"), true) 678 book.SetLogger(log.TestingLogger()) 679 680 r = NewReactor(book, cfg.RecvAsync, conf) 681 r.SetLogger(log.TestingLogger()) 682 return 683 } 684 685 func teardownReactor(book AddrBook) { 686 // FIXME Shouldn't rely on .(*addrBook) assertion 687 err := os.RemoveAll(filepath.Dir(book.(*addrBook).FilePath())) 688 if err != nil { 689 panic(err) 690 } 691 } 692 693 func createSwitchAndAddReactors(reactors ...p2p.Reactor) *p2p.Switch { 694 sw := p2p.MakeSwitch(cfg, 0, "127.0.0.1", "123.123.123", 695 func(i int, sw *p2p.Switch, config *config.P2PConfig) *p2p.Switch { return sw }) 696 sw.SetLogger(log.TestingLogger()) 697 for _, r := range reactors { 698 sw.AddReactor(r.String(), r) 699 r.SetSwitch(sw) 700 } 701 return sw 702 } 703 704 func TestPexVectors(t *testing.T) { 705 addr := tmp2p.NetAddress{ 706 ID: "1", 707 IP: "127.0.0.1", 708 Port: 9090, 709 } 710 711 testCases := []struct { 712 testName string 713 msg proto.Message 714 expBytes string 715 }{ 716 {"PexRequest", &tmp2p.PexRequest{}, "0a00"}, 717 {"PexAddrs", &tmp2p.PexAddrs{Addrs: []tmp2p.NetAddress{addr}}, "12130a110a013112093132372e302e302e31188247"}, 718 } 719 720 for _, tc := range testCases { 721 tc := tc 722 723 w := tc.msg.(p2p.Wrapper).Wrap() 724 bz, err := proto.Marshal(w) 725 require.NoError(t, err) 726 727 require.Equal(t, tc.expBytes, hex.EncodeToString(bz), tc.testName) 728 } 729 }