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