Skip to content

Commit 6b22928

Browse files
addrman: add functionality to select by network
Add an optional parameter to the addrman Select function that allows callers to specify which network the returned address should be on. Ensure that the proper table is selected with different cases of whether the new or tried table has network addresses that match. Co-authored-by: Martin Zumsande <[email protected]>
1 parent 26c3bf1 commit 6b22928

File tree

3 files changed

+43
-20
lines changed

3 files changed

+43
-20
lines changed

src/addrman.cpp

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -714,28 +714,41 @@ void AddrManImpl::Attempt_(const CService& addr, bool fCountFailure, NodeSeconds
714714
}
715715
}
716716

717-
std::pair<CAddress, NodeSeconds> AddrManImpl::Select_(bool new_only) const
717+
std::pair<CAddress, NodeSeconds> AddrManImpl::Select_(bool new_only, std::optional<Network> network) const
718718
{
719719
AssertLockHeld(cs);
720720

721721
if (vRandom.empty()) return {};
722-
if (new_only && nNew == 0) return {};
722+
723+
size_t new_count = nNew;
724+
size_t tried_count = nTried;
725+
726+
if (network.has_value()) {
727+
auto it = m_network_counts.find(*network);
728+
if (it == m_network_counts.end()) return {};
729+
730+
auto counts = it->second;
731+
new_count = counts.n_new;
732+
tried_count = counts.n_tried;
733+
}
734+
735+
if (new_only && new_count == 0) return {};
736+
if (new_count + tried_count == 0) return {};
723737

724738
// Decide if we are going to search the new or tried table
739+
// If either option is viable, use a 50% chance to choose
725740
bool search_tried;
726-
int bucket_count;
727-
728-
// Use a 50% chance for choosing between tried and new table entries.
729-
if (!new_only &&
730-
(nTried > 0 &&
731-
(nNew == 0 || insecure_rand.randbool() == 0))) {
741+
if (new_only || tried_count == 0) {
742+
search_tried = false;
743+
} else if (new_count == 0) {
732744
search_tried = true;
733-
bucket_count = ADDRMAN_TRIED_BUCKET_COUNT;
734745
} else {
735-
search_tried = false;
736-
bucket_count = ADDRMAN_NEW_BUCKET_COUNT;
746+
search_tried = insecure_rand.randbool();
737747
}
738748

749+
const int bucket_count{search_tried ? ADDRMAN_TRIED_BUCKET_COUNT : ADDRMAN_NEW_BUCKET_COUNT};
750+
751+
// Loop through the addrman table until we find an appropriate entry
739752
double chance_factor = 1.0;
740753
while (1) {
741754
// Pick a bucket, and an initial position in that bucket.
@@ -748,7 +761,16 @@ std::pair<CAddress, NodeSeconds> AddrManImpl::Select_(bool new_only) const
748761
for (i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
749762
int position = (initial_position + i) % ADDRMAN_BUCKET_SIZE;
750763
int node_id = GetEntry(search_tried, bucket, position);
751-
if (node_id != -1) break;
764+
if (node_id != -1) {
765+
if (network.has_value()) {
766+
const auto it{mapInfo.find(node_id)};
767+
assert(it != mapInfo.end());
768+
const auto info{it->second};
769+
if (info.GetNetwork() == *network) break;
770+
} else {
771+
break;
772+
}
773+
}
752774
}
753775

754776
// If the bucket is entirely empty, start over with a (likely) different one.
@@ -1168,11 +1190,11 @@ std::pair<CAddress, NodeSeconds> AddrManImpl::SelectTriedCollision()
11681190
return ret;
11691191
}
11701192

1171-
std::pair<CAddress, NodeSeconds> AddrManImpl::Select(bool new_only) const
1193+
std::pair<CAddress, NodeSeconds> AddrManImpl::Select(bool new_only, std::optional<Network> network) const
11721194
{
11731195
LOCK(cs);
11741196
Check();
1175-
auto addrRet = Select_(new_only);
1197+
auto addrRet = Select_(new_only, network);
11761198
Check();
11771199
return addrRet;
11781200
}
@@ -1266,9 +1288,9 @@ std::pair<CAddress, NodeSeconds> AddrMan::SelectTriedCollision()
12661288
return m_impl->SelectTriedCollision();
12671289
}
12681290

1269-
std::pair<CAddress, NodeSeconds> AddrMan::Select(bool new_only) const
1291+
std::pair<CAddress, NodeSeconds> AddrMan::Select(bool new_only, std::optional<Network> network) const
12701292
{
1271-
return m_impl->Select(new_only);
1293+
return m_impl->Select(new_only, network);
12721294
}
12731295

12741296
std::vector<CAddress> AddrMan::GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const

src/addrman.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,12 @@ class AddrMan
146146
/**
147147
* Choose an address to connect to.
148148
*
149-
* @param[in] new_only Whether to only select addresses from the new table.
149+
* @param[in] new_only Whether to only select addresses from the new table.
150+
* @param[in] network Select only addresses of this network (nullopt = all)
150151
* @return CAddress The record for the selected peer.
151152
* seconds The last time we attempted to connect to that peer.
152153
*/
153-
std::pair<CAddress, NodeSeconds> Select(bool new_only = false) const;
154+
std::pair<CAddress, NodeSeconds> Select(bool new_only = false, std::optional<Network> network = std::nullopt) const;
154155

155156
/**
156157
* Return all or many randomly selected addresses, optionally by network.

src/addrman_impl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class AddrManImpl
127127

128128
std::pair<CAddress, NodeSeconds> SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs);
129129

130-
std::pair<CAddress, NodeSeconds> Select(bool new_only) const
130+
std::pair<CAddress, NodeSeconds> Select(bool new_only, std::optional<Network> network) const
131131
EXCLUSIVE_LOCKS_REQUIRED(!cs);
132132

133133
std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
@@ -251,7 +251,7 @@ class AddrManImpl
251251

252252
void Attempt_(const CService& addr, bool fCountFailure, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);
253253

254-
std::pair<CAddress, NodeSeconds> Select_(bool new_only) const EXCLUSIVE_LOCKS_REQUIRED(cs);
254+
std::pair<CAddress, NodeSeconds> Select_(bool new_only, std::optional<Network> network) const EXCLUSIVE_LOCKS_REQUIRED(cs);
255255

256256
/** Helper to generalize looking up an addrman entry from either table.
257257
*

0 commit comments

Comments
 (0)