Skip to content

Commit 58275db

Browse files
committed
Merge bitcoin/bitcoin#23140: Make CAddrman::Select_ select buckets, not positions, first
632aad9 Make CAddrman::Select_ select buckets, not positions, first (Pieter Wuille) Pull request description: The original CAddrMan behaviour (before #5941) was to pick a uniformly random non-empty bucket, and then pick a random element from that bucket. That commit, which introduced deterministic placement of entries in buckets, changed this to picking a uniformly random non-empty bucket position instead. I believe that was a mistake. Buckets are our best metric for spreading out requests across independently-controlled nodes. That does mean that if a bucket has fewer entries, its entries are supposed to be picked more frequently. This PR reverts to the original high-level behavior, but on top of the deterministic placement logic. ACKs for top commit: jnewbery: utACK 632aad9 naumenkogs: ACK 632aad9 mzumsande: ACK 632aad9 Tree-SHA512: 60768afba2b6f0abd0dddff04381cab5acf374df48fc0e883ee16dde7cf7fd33056a04b573cff24a1b4d8e2a645bf0f0b3689eec84da4ff330e7b59ef142eca1
2 parents 02feae5 + 632aad9 commit 58275db

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

src/addrman.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -711,40 +711,56 @@ std::pair<CAddress, int64_t> AddrManImpl::Select_(bool newOnly) const
711711
// use a tried node
712712
double fChanceFactor = 1.0;
713713
while (1) {
714+
// Pick a tried bucket, and an initial position in that bucket.
714715
int nKBucket = insecure_rand.randrange(ADDRMAN_TRIED_BUCKET_COUNT);
715716
int nKBucketPos = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE);
716-
while (vvTried[nKBucket][nKBucketPos] == -1) {
717-
nKBucket = (nKBucket + insecure_rand.randbits(ADDRMAN_TRIED_BUCKET_COUNT_LOG2)) % ADDRMAN_TRIED_BUCKET_COUNT;
718-
nKBucketPos = (nKBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE;
717+
// Iterate over the positions of that bucket, starting at the initial one,
718+
// and looping around.
719+
int i;
720+
for (i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
721+
if (vvTried[nKBucket][(nKBucketPos + i) % ADDRMAN_BUCKET_SIZE] != -1) break;
719722
}
720-
int nId = vvTried[nKBucket][nKBucketPos];
723+
// If the bucket is entirely empty, start over with a (likely) different one.
724+
if (i == ADDRMAN_BUCKET_SIZE) continue;
725+
// Find the entry to return.
726+
int nId = vvTried[nKBucket][(nKBucketPos + i) % ADDRMAN_BUCKET_SIZE];
721727
const auto it_found{mapInfo.find(nId)};
722728
assert(it_found != mapInfo.end());
723729
const AddrInfo& info{it_found->second};
730+
// With probability GetChance() * fChanceFactor, return the entry.
724731
if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30)) {
725732
LogPrint(BCLog::ADDRMAN, "Selected %s from tried\n", info.ToString());
726733
return {info, info.nLastTry};
727734
}
735+
// Otherwise start over with a (likely) different bucket, and increased chance factor.
728736
fChanceFactor *= 1.2;
729737
}
730738
} else {
731739
// use a new node
732740
double fChanceFactor = 1.0;
733741
while (1) {
742+
// Pick a new bucket, and an initial position in that bucket.
734743
int nUBucket = insecure_rand.randrange(ADDRMAN_NEW_BUCKET_COUNT);
735744
int nUBucketPos = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE);
736-
while (vvNew[nUBucket][nUBucketPos] == -1) {
737-
nUBucket = (nUBucket + insecure_rand.randbits(ADDRMAN_NEW_BUCKET_COUNT_LOG2)) % ADDRMAN_NEW_BUCKET_COUNT;
738-
nUBucketPos = (nUBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE;
745+
// Iterate over the positions of that bucket, starting at the initial one,
746+
// and looping around.
747+
int i;
748+
for (i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
749+
if (vvNew[nUBucket][(nUBucketPos + i) % ADDRMAN_BUCKET_SIZE] != -1) break;
739750
}
740-
int nId = vvNew[nUBucket][nUBucketPos];
751+
// If the bucket is entirely empty, start over with a (likely) different one.
752+
if (i == ADDRMAN_BUCKET_SIZE) continue;
753+
// Find the entry to return.
754+
int nId = vvNew[nUBucket][(nUBucketPos + i) % ADDRMAN_BUCKET_SIZE];
741755
const auto it_found{mapInfo.find(nId)};
742756
assert(it_found != mapInfo.end());
743757
const AddrInfo& info{it_found->second};
758+
// With probability GetChance() * fChanceFactor, return the entry.
744759
if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30)) {
745760
LogPrint(BCLog::ADDRMAN, "Selected %s from new\n", info.ToString());
746761
return {info, info.nLastTry};
747762
}
763+
// Otherwise start over with a (likely) different bucket, and increased chance factor.
748764
fChanceFactor *= 1.2;
749765
}
750766
}

0 commit comments

Comments
 (0)