| 701 | } |
| 702 | |
| 703 | std::pair<CAddress, int64_t> AddrManImpl::Select_(bool newOnly) const |
| 704 | { |
| 705 | AssertLockHeld(cs); |
| 706 | |
| 707 | if (vRandom.empty()) return {}; |
| 708 | |
| 709 | if (newOnly && nNew == 0) return {}; |
| 710 | |
| 711 | // Use a 50% chance for choosing between tried and new table entries. |
| 712 | if (!newOnly && |
| 713 | (nTried > 0 && (nNew == 0 || insecure_rand.randbool() == 0))) { |
| 714 | // use a tried node |
| 715 | double fChanceFactor = 1.0; |
| 716 | while (1) { |
| 717 | // Pick a tried bucket, and an initial position in that bucket. |
| 718 | int nKBucket = insecure_rand.randrange(ADDRMAN_TRIED_BUCKET_COUNT); |
| 719 | int nKBucketPos = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE); |
| 720 | // Iterate over the positions of that bucket, starting at the initial one, |
| 721 | // and looping around. |
| 722 | int i; |
| 723 | for (i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) { |
| 724 | if (vvTried[nKBucket][(nKBucketPos + i) % ADDRMAN_BUCKET_SIZE] != -1) break; |
| 725 | } |
| 726 | // If the bucket is entirely empty, start over with a (likely) different one. |
| 727 | if (i == ADDRMAN_BUCKET_SIZE) continue; |
| 728 | // Find the entry to return. |
| 729 | int nId = vvTried[nKBucket][(nKBucketPos + i) % ADDRMAN_BUCKET_SIZE]; |
| 730 | const auto it_found{mapInfo.find(nId)}; |
| 731 | assert(it_found != mapInfo.end()); |
| 732 | const AddrInfo& info{it_found->second}; |
| 733 | // With probability GetChance() * fChanceFactor, return the entry. |
| 734 | if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30)) { |
| 735 | LogPrint(BCLog::ADDRMAN, "Selected %s from tried\n", info.ToString()); |
| 736 | return {info, info.nLastTry}; |
| 737 | } |
| 738 | // Otherwise start over with a (likely) different bucket, and increased chance factor. |
| 739 | fChanceFactor *= 1.2; |
| 740 | } |
| 741 | } else { |
| 742 | // use a new node |
| 743 | double fChanceFactor = 1.0; |
| 744 | while (1) { |
| 745 | // Pick a new bucket, and an initial position in that bucket. |
| 746 | int nUBucket = insecure_rand.randrange(ADDRMAN_NEW_BUCKET_COUNT); |
| 747 | int nUBucketPos = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE); |
| 748 | // Iterate over the positions of that bucket, starting at the initial one, |
| 749 | // and looping around. |
| 750 | int i; |
| 751 | for (i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) { |
| 752 | if (vvNew[nUBucket][(nUBucketPos + i) % ADDRMAN_BUCKET_SIZE] != -1) break; |
| 753 | } |
| 754 | // If the bucket is entirely empty, start over with a (likely) different one. |
| 755 | if (i == ADDRMAN_BUCKET_SIZE) continue; |
| 756 | // Find the entry to return. |
| 757 | int nId = vvNew[nUBucket][(nUBucketPos + i) % ADDRMAN_BUCKET_SIZE]; |
| 758 | const auto it_found{mapInfo.find(nId)}; |
| 759 | assert(it_found != mapInfo.end()); |
| 760 | const AddrInfo& info{it_found->second}; |