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