github.com/Oyster-zx/tendermint@v0.34.24-fork/p2p/pex/addrbook_test.go (about) 1 package pex 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "math" 7 "net" 8 "os" 9 "testing" 10 "time" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 "github.com/tendermint/tendermint/libs/log" 16 tmmath "github.com/tendermint/tendermint/libs/math" 17 tmrand "github.com/tendermint/tendermint/libs/rand" 18 "github.com/tendermint/tendermint/p2p" 19 ) 20 21 // FIXME These tests should not rely on .(*addrBook) assertions 22 23 func TestAddrBookPickAddress(t *testing.T) { 24 fname := createTempFileName("addrbook_test") 25 defer deleteTempFile(fname) 26 27 // 0 addresses 28 book := NewAddrBook(fname, true) 29 book.SetLogger(log.TestingLogger()) 30 assert.Zero(t, book.Size()) 31 32 addr := book.PickAddress(50) 33 assert.Nil(t, addr, "expected no address") 34 35 randAddrs := randNetAddressPairs(t, 1) 36 addrSrc := randAddrs[0] 37 err := book.AddAddress(addrSrc.addr, addrSrc.src) 38 require.NoError(t, err) 39 40 // pick an address when we only have new address 41 addr = book.PickAddress(0) 42 assert.NotNil(t, addr, "expected an address") 43 addr = book.PickAddress(50) 44 assert.NotNil(t, addr, "expected an address") 45 addr = book.PickAddress(100) 46 assert.NotNil(t, addr, "expected an address") 47 48 // pick an address when we only have old address 49 book.MarkGood(addrSrc.addr.ID) 50 addr = book.PickAddress(0) 51 assert.NotNil(t, addr, "expected an address") 52 addr = book.PickAddress(50) 53 assert.NotNil(t, addr, "expected an address") 54 55 // in this case, nNew==0 but we biased 100% to new, so we return nil 56 addr = book.PickAddress(100) 57 assert.Nil(t, addr, "did not expected an address") 58 } 59 60 func TestAddrBookSaveLoad(t *testing.T) { 61 fname := createTempFileName("addrbook_test") 62 defer deleteTempFile(fname) 63 64 // 0 addresses 65 book := NewAddrBook(fname, true) 66 book.SetLogger(log.TestingLogger()) 67 book.Save() 68 69 book = NewAddrBook(fname, true) 70 book.SetLogger(log.TestingLogger()) 71 err := book.Start() 72 require.NoError(t, err) 73 74 assert.True(t, book.Empty()) 75 76 // 100 addresses 77 randAddrs := randNetAddressPairs(t, 100) 78 79 for _, addrSrc := range randAddrs { 80 err := book.AddAddress(addrSrc.addr, addrSrc.src) 81 require.NoError(t, err) 82 } 83 84 assert.Equal(t, 100, book.Size()) 85 book.Save() 86 87 book = NewAddrBook(fname, true) 88 book.SetLogger(log.TestingLogger()) 89 err = book.Start() 90 require.NoError(t, err) 91 92 assert.Equal(t, 100, book.Size()) 93 } 94 95 func TestAddrBookLookup(t *testing.T) { 96 fname := createTempFileName("addrbook_test") 97 defer deleteTempFile(fname) 98 99 randAddrs := randNetAddressPairs(t, 100) 100 101 book := NewAddrBook(fname, true) 102 book.SetLogger(log.TestingLogger()) 103 for _, addrSrc := range randAddrs { 104 addr := addrSrc.addr 105 src := addrSrc.src 106 err := book.AddAddress(addr, src) 107 require.NoError(t, err) 108 109 ka := book.HasAddress(addr) 110 assert.True(t, ka, "Expected to find KnownAddress %v but wasn't there.", addr) 111 } 112 } 113 114 func TestAddrBookPromoteToOld(t *testing.T) { 115 fname := createTempFileName("addrbook_test") 116 defer deleteTempFile(fname) 117 118 randAddrs := randNetAddressPairs(t, 100) 119 120 book := NewAddrBook(fname, true) 121 book.SetLogger(log.TestingLogger()) 122 for _, addrSrc := range randAddrs { 123 err := book.AddAddress(addrSrc.addr, addrSrc.src) 124 require.NoError(t, err) 125 } 126 127 // Attempt all addresses. 128 for _, addrSrc := range randAddrs { 129 book.MarkAttempt(addrSrc.addr) 130 } 131 132 // Promote half of them 133 for i, addrSrc := range randAddrs { 134 if i%2 == 0 { 135 book.MarkGood(addrSrc.addr.ID) 136 } 137 } 138 139 // TODO: do more testing :) 140 141 selection := book.GetSelection() 142 t.Logf("selection: %v", selection) 143 144 if len(selection) > book.Size() { 145 t.Errorf("selection could not be bigger than the book") 146 } 147 148 selection = book.GetSelectionWithBias(30) 149 t.Logf("selection: %v", selection) 150 151 if len(selection) > book.Size() { 152 t.Errorf("selection with bias could not be bigger than the book") 153 } 154 155 assert.Equal(t, book.Size(), 100, "expecting book size to be 100") 156 } 157 158 func TestAddrBookHandlesDuplicates(t *testing.T) { 159 fname := createTempFileName("addrbook_test") 160 defer deleteTempFile(fname) 161 162 book := NewAddrBook(fname, true) 163 book.SetLogger(log.TestingLogger()) 164 165 randAddrs := randNetAddressPairs(t, 100) 166 167 differentSrc := randIPv4Address(t) 168 for _, addrSrc := range randAddrs { 169 err := book.AddAddress(addrSrc.addr, addrSrc.src) 170 require.NoError(t, err) 171 err = book.AddAddress(addrSrc.addr, addrSrc.src) // duplicate 172 require.NoError(t, err) 173 err = book.AddAddress(addrSrc.addr, differentSrc) // different src 174 require.NoError(t, err) 175 } 176 177 assert.Equal(t, 100, book.Size()) 178 } 179 180 type netAddressPair struct { 181 addr *p2p.NetAddress 182 src *p2p.NetAddress 183 } 184 185 func randNetAddressPairs(t *testing.T, n int) []netAddressPair { 186 randAddrs := make([]netAddressPair, n) 187 for i := 0; i < n; i++ { 188 randAddrs[i] = netAddressPair{addr: randIPv4Address(t), src: randIPv4Address(t)} 189 } 190 return randAddrs 191 } 192 193 func randIPv4Address(t *testing.T) *p2p.NetAddress { 194 for { 195 ip := fmt.Sprintf("%v.%v.%v.%v", 196 tmrand.Intn(254)+1, 197 tmrand.Intn(255), 198 tmrand.Intn(255), 199 tmrand.Intn(255), 200 ) 201 port := tmrand.Intn(65535-1) + 1 202 id := p2p.ID(hex.EncodeToString(tmrand.Bytes(p2p.IDByteLength))) 203 idAddr := p2p.IDAddressString(id, fmt.Sprintf("%v:%v", ip, port)) 204 addr, err := p2p.NewNetAddressString(idAddr) 205 assert.Nil(t, err, "error generating rand network address") 206 if addr.Routable() { 207 return addr 208 } 209 } 210 } 211 212 func TestAddrBookRemoveAddress(t *testing.T) { 213 fname := createTempFileName("addrbook_test") 214 defer deleteTempFile(fname) 215 216 book := NewAddrBook(fname, true) 217 book.SetLogger(log.TestingLogger()) 218 219 addr := randIPv4Address(t) 220 err := book.AddAddress(addr, addr) 221 require.NoError(t, err) 222 assert.Equal(t, 1, book.Size()) 223 224 book.RemoveAddress(addr) 225 assert.Equal(t, 0, book.Size()) 226 227 nonExistingAddr := randIPv4Address(t) 228 book.RemoveAddress(nonExistingAddr) 229 assert.Equal(t, 0, book.Size()) 230 } 231 232 func TestAddrBookGetSelectionWithOneMarkedGood(t *testing.T) { 233 // create a book with 10 addresses, 1 good/old and 9 new 234 book, fname := createAddrBookWithMOldAndNNewAddrs(t, 1, 9) 235 defer deleteTempFile(fname) 236 237 addrs := book.GetSelectionWithBias(biasToSelectNewPeers) 238 assert.NotNil(t, addrs) 239 assertMOldAndNNewAddrsInSelection(t, 1, 9, addrs, book) 240 } 241 242 func TestAddrBookGetSelectionWithOneNotMarkedGood(t *testing.T) { 243 // create a book with 10 addresses, 9 good/old and 1 new 244 book, fname := createAddrBookWithMOldAndNNewAddrs(t, 9, 1) 245 defer deleteTempFile(fname) 246 247 addrs := book.GetSelectionWithBias(biasToSelectNewPeers) 248 assert.NotNil(t, addrs) 249 assertMOldAndNNewAddrsInSelection(t, 9, 1, addrs, book) 250 } 251 252 func TestAddrBookGetSelectionReturnsNilWhenAddrBookIsEmpty(t *testing.T) { 253 book, fname := createAddrBookWithMOldAndNNewAddrs(t, 0, 0) 254 defer deleteTempFile(fname) 255 256 addrs := book.GetSelectionWithBias(biasToSelectNewPeers) 257 assert.Nil(t, addrs) 258 } 259 260 func TestAddrBookGetSelection(t *testing.T) { 261 fname := createTempFileName("addrbook_test") 262 defer deleteTempFile(fname) 263 264 book := NewAddrBook(fname, true) 265 book.SetLogger(log.TestingLogger()) 266 267 // 1) empty book 268 assert.Empty(t, book.GetSelection()) 269 270 // 2) add one address 271 addr := randIPv4Address(t) 272 err := book.AddAddress(addr, addr) 273 require.NoError(t, err) 274 275 assert.Equal(t, 1, len(book.GetSelection())) 276 assert.Equal(t, addr, book.GetSelection()[0]) 277 278 // 3) add a bunch of addresses 279 randAddrs := randNetAddressPairs(t, 100) 280 for _, addrSrc := range randAddrs { 281 err := book.AddAddress(addrSrc.addr, addrSrc.src) 282 require.NoError(t, err) 283 } 284 285 // check there is no duplicates 286 addrs := make(map[string]*p2p.NetAddress) 287 selection := book.GetSelection() 288 for _, addr := range selection { 289 if dup, ok := addrs[addr.String()]; ok { 290 t.Fatalf("selection %v contains duplicates %v", selection, dup) 291 } 292 addrs[addr.String()] = addr 293 } 294 295 if len(selection) > book.Size() { 296 t.Errorf("selection %v could not be bigger than the book", selection) 297 } 298 } 299 300 func TestAddrBookGetSelectionWithBias(t *testing.T) { 301 const biasTowardsNewAddrs = 30 302 303 fname := createTempFileName("addrbook_test") 304 defer deleteTempFile(fname) 305 306 book := NewAddrBook(fname, true) 307 book.SetLogger(log.TestingLogger()) 308 309 // 1) empty book 310 selection := book.GetSelectionWithBias(biasTowardsNewAddrs) 311 assert.Empty(t, selection) 312 313 // 2) add one address 314 addr := randIPv4Address(t) 315 err := book.AddAddress(addr, addr) 316 require.NoError(t, err) 317 318 selection = book.GetSelectionWithBias(biasTowardsNewAddrs) 319 assert.Equal(t, 1, len(selection)) 320 assert.Equal(t, addr, selection[0]) 321 322 // 3) add a bunch of addresses 323 randAddrs := randNetAddressPairs(t, 100) 324 for _, addrSrc := range randAddrs { 325 err := book.AddAddress(addrSrc.addr, addrSrc.src) 326 require.NoError(t, err) 327 } 328 329 // check there is no duplicates 330 addrs := make(map[string]*p2p.NetAddress) 331 selection = book.GetSelectionWithBias(biasTowardsNewAddrs) 332 for _, addr := range selection { 333 if dup, ok := addrs[addr.String()]; ok { 334 t.Fatalf("selection %v contains duplicates %v", selection, dup) 335 } 336 addrs[addr.String()] = addr 337 } 338 339 if len(selection) > book.Size() { 340 t.Fatalf("selection %v could not be bigger than the book", selection) 341 } 342 343 // 4) mark 80% of the addresses as good 344 randAddrsLen := len(randAddrs) 345 for i, addrSrc := range randAddrs { 346 if int((float64(i)/float64(randAddrsLen))*100) >= 20 { 347 book.MarkGood(addrSrc.addr.ID) 348 } 349 } 350 351 selection = book.GetSelectionWithBias(biasTowardsNewAddrs) 352 353 // check that ~70% of addresses returned are good 354 good := 0 355 for _, addr := range selection { 356 if book.IsGood(addr) { 357 good++ 358 } 359 } 360 361 got, expected := int((float64(good)/float64(len(selection)))*100), 100-biasTowardsNewAddrs 362 363 // compute some slack to protect against small differences due to rounding: 364 slack := int(math.Round(float64(100) / float64(len(selection)))) 365 if got > expected+slack { 366 t.Fatalf( 367 "got more good peers (%% got: %d, %% expected: %d, number of good addrs: %d, total: %d)", 368 got, 369 expected, 370 good, 371 len(selection), 372 ) 373 } 374 if got < expected-slack { 375 t.Fatalf( 376 "got fewer good peers (%% got: %d, %% expected: %d, number of good addrs: %d, total: %d)", 377 got, 378 expected, 379 good, 380 len(selection), 381 ) 382 } 383 } 384 385 func TestAddrBookHasAddress(t *testing.T) { 386 fname := createTempFileName("addrbook_test") 387 defer deleteTempFile(fname) 388 389 book := NewAddrBook(fname, true) 390 book.SetLogger(log.TestingLogger()) 391 addr := randIPv4Address(t) 392 err := book.AddAddress(addr, addr) 393 require.NoError(t, err) 394 395 assert.True(t, book.HasAddress(addr)) 396 397 book.RemoveAddress(addr) 398 399 assert.False(t, book.HasAddress(addr)) 400 } 401 402 func testCreatePrivateAddrs(t *testing.T, numAddrs int) ([]*p2p.NetAddress, []string) { 403 addrs := make([]*p2p.NetAddress, numAddrs) 404 for i := 0; i < numAddrs; i++ { 405 addrs[i] = randIPv4Address(t) 406 } 407 408 private := make([]string, numAddrs) 409 for i, addr := range addrs { 410 private[i] = string(addr.ID) 411 } 412 return addrs, private 413 } 414 415 func TestBanBadPeers(t *testing.T) { 416 fname := createTempFileName("addrbook_test") 417 defer deleteTempFile(fname) 418 419 book := NewAddrBook(fname, true) 420 book.SetLogger(log.TestingLogger()) 421 422 addr := randIPv4Address(t) 423 _ = book.AddAddress(addr, addr) 424 425 book.MarkBad(addr, 1*time.Second) 426 // addr should not reachable 427 assert.False(t, book.HasAddress(addr)) 428 assert.True(t, book.IsBanned(addr)) 429 430 err := book.AddAddress(addr, addr) 431 // book should not add address from the blacklist 432 assert.Error(t, err) 433 434 time.Sleep(1 * time.Second) 435 book.ReinstateBadPeers() 436 // address should be reinstated in the new bucket 437 assert.EqualValues(t, 1, book.Size()) 438 assert.True(t, book.HasAddress(addr)) 439 assert.False(t, book.IsGood(addr)) 440 } 441 442 func TestAddrBookEmpty(t *testing.T) { 443 fname := createTempFileName("addrbook_test") 444 defer deleteTempFile(fname) 445 446 book := NewAddrBook(fname, true) 447 book.SetLogger(log.TestingLogger()) 448 // Check that empty book is empty 449 require.True(t, book.Empty()) 450 // Check that book with our address is empty 451 book.AddOurAddress(randIPv4Address(t)) 452 require.True(t, book.Empty()) 453 // Check that book with private addrs is empty 454 _, privateIds := testCreatePrivateAddrs(t, 5) 455 book.AddPrivateIDs(privateIds) 456 require.True(t, book.Empty()) 457 458 // Check that book with address is not empty 459 err := book.AddAddress(randIPv4Address(t), randIPv4Address(t)) 460 require.NoError(t, err) 461 require.False(t, book.Empty()) 462 } 463 464 func TestPrivatePeers(t *testing.T) { 465 fname := createTempFileName("addrbook_test") 466 defer deleteTempFile(fname) 467 468 book := NewAddrBook(fname, true) 469 book.SetLogger(log.TestingLogger()) 470 471 addrs, private := testCreatePrivateAddrs(t, 10) 472 book.AddPrivateIDs(private) 473 474 // private addrs must not be added 475 for _, addr := range addrs { 476 err := book.AddAddress(addr, addr) 477 if assert.Error(t, err) { 478 _, ok := err.(ErrAddrBookPrivate) 479 assert.True(t, ok) 480 } 481 } 482 483 // addrs coming from private peers must not be added 484 err := book.AddAddress(randIPv4Address(t), addrs[0]) 485 if assert.Error(t, err) { 486 _, ok := err.(ErrAddrBookPrivateSrc) 487 assert.True(t, ok) 488 } 489 } 490 491 func testAddrBookAddressSelection(t *testing.T, bookSize int) { 492 // generate all combinations of old (m) and new addresses 493 for nBookOld := 0; nBookOld <= bookSize; nBookOld++ { 494 nBookNew := bookSize - nBookOld 495 dbgStr := fmt.Sprintf("book of size %d (new %d, old %d)", bookSize, nBookNew, nBookOld) 496 497 // create book and get selection 498 book, fname := createAddrBookWithMOldAndNNewAddrs(t, nBookOld, nBookNew) 499 defer deleteTempFile(fname) 500 addrs := book.GetSelectionWithBias(biasToSelectNewPeers) 501 assert.NotNil(t, addrs, "%s - expected a non-nil selection", dbgStr) 502 nAddrs := len(addrs) 503 assert.NotZero(t, nAddrs, "%s - expected at least one address in selection", dbgStr) 504 505 // check there's no nil addresses 506 for _, addr := range addrs { 507 if addr == nil { 508 t.Fatalf("%s - got nil address in selection %v", dbgStr, addrs) 509 } 510 } 511 512 // XXX: shadowing 513 nOld, nNew := countOldAndNewAddrsInSelection(addrs, book) 514 515 // Given: 516 // n - num new addrs, m - num old addrs 517 // k - num new addrs expected in the beginning (based on bias %) 518 // i=min(n, max(k,r-m)), aka expNew 519 // j=min(m, r-i), aka expOld 520 // 521 // We expect this layout: 522 // indices: 0...i-1 i...i+j-1 523 // addresses: N0..Ni-1 O0..Oj-1 524 // 525 // There is at least one partition and at most three. 526 var ( 527 k = percentageOfNum(biasToSelectNewPeers, nAddrs) 528 expNew = tmmath.MinInt(nNew, tmmath.MaxInt(k, nAddrs-nBookOld)) 529 expOld = tmmath.MinInt(nOld, nAddrs-expNew) 530 ) 531 532 // Verify that the number of old and new addresses are as expected 533 if nNew != expNew { 534 t.Fatalf("%s - expected new addrs %d, got %d", dbgStr, expNew, nNew) 535 } 536 if nOld != expOld { 537 t.Fatalf("%s - expected old addrs %d, got %d", dbgStr, expOld, nOld) 538 } 539 540 // Verify that the order of addresses is as expected 541 // Get the sequence types and lengths of the selection 542 seqLens, seqTypes, err := analyseSelectionLayout(book, addrs) 543 assert.NoError(t, err, "%s", dbgStr) 544 545 // Build a list with the expected lengths of partitions and another with the expected types, e.g.: 546 // expSeqLens = [10, 22], expSeqTypes = [1, 2] 547 // means we expect 10 new (type 1) addresses followed by 22 old (type 2) addresses. 548 var expSeqLens []int 549 var expSeqTypes []int 550 551 switch { 552 case expOld == 0: // all new addresses 553 expSeqLens = []int{nAddrs} 554 expSeqTypes = []int{1} 555 case expNew == 0: // all old addresses 556 expSeqLens = []int{nAddrs} 557 expSeqTypes = []int{2} 558 case nAddrs-expNew-expOld == 0: // new addresses, old addresses 559 expSeqLens = []int{expNew, expOld} 560 expSeqTypes = []int{1, 2} 561 } 562 563 assert.Equal(t, expSeqLens, seqLens, 564 "%s - expected sequence lengths of old/new %v, got %v", 565 dbgStr, expSeqLens, seqLens) 566 assert.Equal(t, expSeqTypes, seqTypes, 567 "%s - expected sequence types (1-new, 2-old) was %v, got %v", 568 dbgStr, expSeqTypes, seqTypes) 569 } 570 } 571 572 func TestMultipleAddrBookAddressSelection(t *testing.T) { 573 // test books with smaller size, < N 574 const N = 32 575 for bookSize := 1; bookSize < N; bookSize++ { 576 testAddrBookAddressSelection(t, bookSize) 577 } 578 579 // Test for two books with sizes from following ranges 580 ranges := [...][]int{{33, 100}, {100, 175}} 581 bookSizes := make([]int, 0, len(ranges)) 582 for _, r := range ranges { 583 bookSizes = append(bookSizes, tmrand.Intn(r[1]-r[0])+r[0]) 584 } 585 t.Logf("Testing address selection for the following book sizes %v\n", bookSizes) 586 for _, bookSize := range bookSizes { 587 testAddrBookAddressSelection(t, bookSize) 588 } 589 } 590 591 func TestAddrBookAddDoesNotOverwriteOldIP(t *testing.T) { 592 fname := createTempFileName("addrbook_test") 593 defer deleteTempFile(fname) 594 595 // This test creates adds a peer to the address book and marks it good 596 // It then attempts to override the peer's IP, by adding a peer with the same ID 597 // but different IP. We distinguish the IP's by "RealIP" and "OverrideAttemptIP" 598 peerID := "678503e6c8f50db7279c7da3cb9b072aac4bc0d5" 599 peerRealIP := "1.1.1.1:26656" 600 peerOverrideAttemptIP := "2.2.2.2:26656" 601 SrcAddr := "b0dd378c3fbc4c156cd6d302a799f0d2e4227201@159.89.121.174:26656" 602 603 // There is a chance that AddAddress will ignore the new peer its given. 604 // So we repeat trying to override the peer several times, 605 // to ensure we aren't in a case that got probabilistically ignored 606 numOverrideAttempts := 10 607 608 peerRealAddr, err := p2p.NewNetAddressString(peerID + "@" + peerRealIP) 609 require.Nil(t, err) 610 611 peerOverrideAttemptAddr, err := p2p.NewNetAddressString(peerID + "@" + peerOverrideAttemptIP) 612 require.Nil(t, err) 613 614 src, err := p2p.NewNetAddressString(SrcAddr) 615 require.Nil(t, err) 616 617 book := NewAddrBook(fname, true) 618 book.SetLogger(log.TestingLogger()) 619 err = book.AddAddress(peerRealAddr, src) 620 require.Nil(t, err) 621 book.MarkAttempt(peerRealAddr) 622 book.MarkGood(peerRealAddr.ID) 623 624 // Double check that adding a peer again doesn't error 625 err = book.AddAddress(peerRealAddr, src) 626 require.Nil(t, err) 627 628 // Try changing ip but keeping the same node id. (change 1.1.1.1 to 2.2.2.2) 629 // This should just be ignored, and not error. 630 for i := 0; i < numOverrideAttempts; i++ { 631 err = book.AddAddress(peerOverrideAttemptAddr, src) 632 require.Nil(t, err) 633 } 634 // Now check that the IP was not overridden. 635 // This is done by sampling several peers from addr book 636 // and ensuring they all have the correct IP. 637 // In the expected functionality, this test should only have 1 Peer, hence will pass. 638 for i := 0; i < numOverrideAttempts; i++ { 639 selection := book.GetSelection() 640 for _, addr := range selection { 641 require.Equal(t, addr.IP, peerRealAddr.IP) 642 } 643 } 644 } 645 646 func TestAddrBookGroupKey(t *testing.T) { 647 // non-strict routability 648 testCases := []struct { 649 name string 650 ip string 651 expKey string 652 }{ 653 // IPv4 normal. 654 {"ipv4 normal class a", "12.1.2.3", "12.1.0.0"}, 655 {"ipv4 normal class b", "173.1.2.3", "173.1.0.0"}, 656 {"ipv4 normal class c", "196.1.2.3", "196.1.0.0"}, 657 658 // IPv6/IPv4 translations. 659 {"ipv6 rfc3964 with ipv4 encap", "2002:0c01:0203::", "12.1.0.0"}, 660 {"ipv6 rfc4380 toredo ipv4", "2001:0:1234::f3fe:fdfc", "12.1.0.0"}, 661 {"ipv6 rfc6052 well-known prefix with ipv4", "64:ff9b::0c01:0203", "12.1.0.0"}, 662 {"ipv6 rfc6145 translated ipv4", "::ffff:0:0c01:0203", "12.1.0.0"}, 663 664 // Tor. 665 {"ipv6 tor onioncat", "fd87:d87e:eb43:1234::5678", "tor:2"}, 666 {"ipv6 tor onioncat 2", "fd87:d87e:eb43:1245::6789", "tor:2"}, 667 {"ipv6 tor onioncat 3", "fd87:d87e:eb43:1345::6789", "tor:3"}, 668 669 // IPv6 normal. 670 {"ipv6 normal", "2602:100::1", "2602:100::"}, 671 {"ipv6 normal 2", "2602:0100::1234", "2602:100::"}, 672 {"ipv6 hurricane electric", "2001:470:1f10:a1::2", "2001:470:1000::"}, 673 {"ipv6 hurricane electric 2", "2001:0470:1f10:a1::2", "2001:470:1000::"}, 674 } 675 676 for i, tc := range testCases { 677 nip := net.ParseIP(tc.ip) 678 key := groupKeyFor(p2p.NewNetAddressIPPort(nip, 26656), false) 679 assert.Equal(t, tc.expKey, key, "#%d", i) 680 } 681 682 // strict routability 683 testCases = []struct { 684 name string 685 ip string 686 expKey string 687 }{ 688 // Local addresses. 689 {"ipv4 localhost", "127.0.0.1", "local"}, 690 {"ipv6 localhost", "::1", "local"}, 691 {"ipv4 zero", "0.0.0.0", "local"}, 692 {"ipv4 first octet zero", "0.1.2.3", "local"}, 693 694 // Unroutable addresses. 695 {"ipv4 invalid bcast", "255.255.255.255", "unroutable"}, 696 {"ipv4 rfc1918 10/8", "10.1.2.3", "unroutable"}, 697 {"ipv4 rfc1918 172.16/12", "172.16.1.2", "unroutable"}, 698 {"ipv4 rfc1918 192.168/16", "192.168.1.2", "unroutable"}, 699 {"ipv6 rfc3849 2001:db8::/32", "2001:db8::1234", "unroutable"}, 700 {"ipv4 rfc3927 169.254/16", "169.254.1.2", "unroutable"}, 701 {"ipv6 rfc4193 fc00::/7", "fc00::1234", "unroutable"}, 702 {"ipv6 rfc4843 2001:10::/28", "2001:10::1234", "unroutable"}, 703 {"ipv6 rfc4862 fe80::/64", "fe80::1234", "unroutable"}, 704 } 705 706 for i, tc := range testCases { 707 nip := net.ParseIP(tc.ip) 708 key := groupKeyFor(p2p.NewNetAddressIPPort(nip, 26656), true) 709 assert.Equal(t, tc.expKey, key, "#%d", i) 710 } 711 } 712 713 func assertMOldAndNNewAddrsInSelection(t *testing.T, m, n int, addrs []*p2p.NetAddress, book *addrBook) { 714 nOld, nNew := countOldAndNewAddrsInSelection(addrs, book) 715 assert.Equal(t, m, nOld, "old addresses") 716 assert.Equal(t, n, nNew, "new addresses") 717 } 718 719 func createTempFileName(prefix string) string { 720 f, err := os.CreateTemp("", prefix) 721 if err != nil { 722 panic(err) 723 } 724 fname := f.Name() 725 err = f.Close() 726 if err != nil { 727 panic(err) 728 } 729 return fname 730 } 731 732 func deleteTempFile(fname string) { 733 err := os.Remove(fname) 734 if err != nil { 735 panic(err) 736 } 737 } 738 739 func createAddrBookWithMOldAndNNewAddrs(t *testing.T, nOld, nNew int) (book *addrBook, fname string) { 740 fname = createTempFileName("addrbook_test") 741 742 book = NewAddrBook(fname, true).(*addrBook) 743 book.SetLogger(log.TestingLogger()) 744 assert.Zero(t, book.Size()) 745 746 randAddrs := randNetAddressPairs(t, nOld) 747 for _, addr := range randAddrs { 748 err := book.AddAddress(addr.addr, addr.src) 749 require.NoError(t, err) 750 book.MarkGood(addr.addr.ID) 751 } 752 753 randAddrs = randNetAddressPairs(t, nNew) 754 for _, addr := range randAddrs { 755 err := book.AddAddress(addr.addr, addr.src) 756 require.NoError(t, err) 757 } 758 759 return 760 } 761 762 func countOldAndNewAddrsInSelection(addrs []*p2p.NetAddress, book *addrBook) (nOld, nNew int) { 763 for _, addr := range addrs { 764 if book.IsGood(addr) { 765 nOld++ 766 } else { 767 nNew++ 768 } 769 } 770 return 771 } 772 773 // Analyse the layout of the selection specified by 'addrs' 774 // Returns: 775 // - seqLens - the lengths of the sequences of addresses of same type 776 // - seqTypes - the types of sequences in selection 777 func analyseSelectionLayout(book *addrBook, addrs []*p2p.NetAddress) (seqLens, seqTypes []int, err error) { 778 // address types are: 0 - nil, 1 - new, 2 - old 779 var ( 780 prevType = 0 781 currentSeqLen = 0 782 ) 783 784 for _, addr := range addrs { 785 addrType := 0 786 if book.IsGood(addr) { 787 addrType = 2 788 } else { 789 addrType = 1 790 } 791 if addrType != prevType && prevType != 0 { 792 seqLens = append(seqLens, currentSeqLen) 793 seqTypes = append(seqTypes, prevType) 794 currentSeqLen = 0 795 } 796 currentSeqLen++ 797 prevType = addrType 798 } 799 800 seqLens = append(seqLens, currentSeqLen) 801 seqTypes = append(seqTypes, prevType) 802 803 return 804 }