6#include <bitcoin-build-config.h>
37 std::vector<unsigned char> vchSourceGroupKey = netgroupman.
GetGroup(src);
38 uint64_t hash1 = (
HashWriter{} << nKey << netgroupman.
GetGroup(*
this) << vchSourceGroupKey).GetCheapHash();
45 uint64_t hash1 = (
HashWriter{} << nKey << (fNew ? uint8_t{
'N'} : uint8_t{
'K'}) << bucket <<
GetKey()).GetCheapHash();
55 if (
nTime > now + 10min) {
84 fChance *= pow(0.66, std::min(
nAttempts, 8));
90 : insecure_rand{deterministic}
91 , nKey{deterministic ?
uint256{1} : insecure_rand.rand256()}
92 , m_consistency_check_ratio{consistency_check_ratio}
93 , m_netgroupman{netgroupman}
95 for (
auto& bucket : vvNew) {
96 for (
auto& entry : bucket) {
100 for (
auto& bucket : vvTried) {
101 for (
auto& entry : bucket) {
112template <
typename Stream>
162 static constexpr uint8_t lowest_compatible = Format::V4_MULTIPORT;
171 std::unordered_map<nid_type, int> mapUnkIds;
173 for (
const auto& entry : mapInfo) {
174 mapUnkIds[entry.first] = nIds;
175 const AddrInfo& info = entry.second;
183 for (
const auto& entry : mapInfo) {
184 const AddrInfo& info = entry.second;
194 if (vvNew[bucket][i] != -1)
199 if (vvNew[bucket][i] != -1) {
200 int nIndex = mapUnkIds[vvNew[bucket][i]];
210template <
typename Stream>
218 s_ >> Using<CustomUintFormatter<1>>(
format);
227 "Corrupted addrman database: The compat value (%u) "
228 "is lower than the expected minimum value %u.",
234 "Unsupported format of addrman database: %u. It is compatible with formats >=%u, "
235 "but the maximum supported by this version of %s is %u.",
244 if (
format >= Format::V1_DETERMINISTIC) {
245 nUBuckets ^= (1 << 30);
249 throw std::ios_base::failure(
250 strprintf(
"Corrupt AddrMan serialization: nNew=%d, should be in [0, %d]",
256 throw std::ios_base::failure(
257 strprintf(
"Corrupt AddrMan serialization: nTried=%d, should be in [0, %d]",
263 for (
int n = 0; n < nNew; n++) {
268 vRandom.push_back(n);
275 for (
int n = 0; n < nTried; n++) {
281 && vvTried[nKBucket][nKBucketPos] == -1) {
284 vRandom.push_back(nIdCount);
285 mapInfo[nIdCount] = info;
286 mapAddr[info] = nIdCount;
287 vvTried[nKBucket][nKBucketPos] = nIdCount;
289 m_network_counts[info.
GetNetwork()].n_tried++;
299 std::vector<std::pair<int, int>> bucket_entries;
301 for (
int bucket = 0; bucket < nUBuckets; ++bucket) {
304 for (
int n = 0; n < num_entries; ++n) {
307 if (entry_index >= 0 && entry_index < nNew) {
308 bucket_entries.emplace_back(bucket, entry_index);
317 uint256 serialized_asmap_version;
318 if (
format >= Format::V2_ASMAP) {
319 s >> serialized_asmap_version;
322 serialized_asmap_version == supplied_asmap_version};
324 if (!restore_bucketing) {
328 for (
auto bucket_entry : bucket_entries) {
329 int bucket{bucket_entry.first};
330 const int entry_index{bucket_entry.second};
331 AddrInfo& info = mapInfo[entry_index];
342 if (restore_bucketing && vvNew[bucket][bucket_position] == -1) {
344 vvNew[bucket][bucket_position] = entry_index;
351 if (vvNew[bucket][bucket_position] == -1) {
352 vvNew[bucket][bucket_position] = entry_index;
360 for (
auto it = mapInfo.cbegin(); it != mapInfo.cend(); ) {
361 if (it->second.fInTried ==
false && it->second.nRefCount == 0) {
362 const auto itCopy = it++;
369 if (nLost + nLostUnk > 0) {
370 LogDebug(
BCLog::ADDRMAN,
"addrman lost %i new and %i tried addresses due to collisions or invalid addresses\n", nLostUnk, nLost);
374 if (check_code != 0) {
376 "Corrupt data. Consistency check failed with code %s",
385 const auto it = mapAddr.find(addr);
386 if (it == mapAddr.end())
389 *pnId = (*it).second;
390 const auto it2 = mapInfo.find((*it).second);
391 if (it2 != mapInfo.end())
392 return &(*it2).second;
401 mapInfo[nId] =
AddrInfo(addr, addrSource);
403 mapInfo[nId].nRandomPos = vRandom.size();
404 vRandom.push_back(nId);
409 return &mapInfo[nId];
416 if (nRndPos1 == nRndPos2)
419 assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
424 const auto it_1{mapInfo.find(nId1)};
425 const auto it_2{mapInfo.find(nId2)};
426 assert(it_1 != mapInfo.end());
427 assert(it_2 != mapInfo.end());
429 it_1->second.nRandomPos = nRndPos2;
430 it_2->second.nRandomPos = nRndPos1;
432 vRandom[nRndPos1] = nId2;
433 vRandom[nRndPos2] = nId1;
440 assert(mapInfo.contains(nId));
458 if (vvNew[nUBucket][nUBucketPos] != -1) {
459 nid_type nIdDelete = vvNew[nUBucket][nUBucketPos];
460 AddrInfo& infoDelete = mapInfo[nIdDelete];
463 vvNew[nUBucket][nUBucketPos] = -1;
480 if (vvNew[bucket][pos] == nId) {
481 vvNew[bucket][pos] = -1;
496 if (vvTried[nKBucket][nKBucketPos] != -1) {
498 nid_type nIdEvict = vvTried[nKBucket][nKBucketPos];
499 assert(mapInfo.contains(nIdEvict));
500 AddrInfo& infoOld = mapInfo[nIdEvict];
504 vvTried[nKBucket][nKBucketPos] = -1;
506 m_network_counts[infoOld.
GetNetwork()].n_tried--;
512 assert(vvNew[nUBucket][nUBucketPos] == -1);
516 vvNew[nUBucket][nUBucketPos] = nIdEvict;
518 m_network_counts[infoOld.
GetNetwork()].n_new++;
522 assert(vvTried[nKBucket][nKBucketPos] == -1);
524 vvTried[nKBucket][nKBucketPos] = nId;
527 m_network_counts[info.
GetNetwork()].n_tried++;
548 const auto update_interval{currently_online ? 1h : 24h};
549 if (pinfo->
nTime < addr.
nTime - update_interval - time_penalty) {
571 const int nFactor{1 << pinfo->
nRefCount};
572 if (insecure_rand.randrange(nFactor) != 0)
return false;
581 bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
582 if (vvNew[nUBucket][nUBucketPos] != nId) {
584 AddrInfo& infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]];
593 vvNew[nUBucket][nUBucketPos] = nId;
617 if (!pinfo)
return false;
640 if (test_before_evict && (vvTried[tried_bucket][tried_bucket_pos] != -1)) {
645 auto colliding_entry = mapInfo.find(vvTried[tried_bucket][tried_bucket_pos]);
647 colliding_entry != mapInfo.end() ? colliding_entry->second.ToStringAddrPort() :
"<unknown-addr>",
664 for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++) {
668 LogDebug(
BCLog::ADDRMAN,
"Added %i addresses (of %i) from %s: %i tried, %i new\n", added, vAddr.size(),
source.ToStringAddr(), nTried, nNew);
693std::pair<CAddress, NodeSeconds>
AddrManImpl::Select_(
bool new_only,
const std::unordered_set<Network>& networks)
const
697 if (vRandom.empty())
return {};
699 size_t new_count = nNew;
700 size_t tried_count = nTried;
702 if (!networks.empty()) {
705 for (
auto& network : networks) {
706 auto it = m_network_counts.find(network);
707 if (it == m_network_counts.end()) {
710 auto counts = it->second;
711 new_count += counts.n_new;
712 tried_count += counts.n_tried;
716 if (new_only && new_count == 0)
return {};
717 if (new_count + tried_count == 0)
return {};
722 if (new_only || tried_count == 0) {
723 search_tried =
false;
724 }
else if (new_count == 0) {
727 search_tried = insecure_rand.randbool();
733 double chance_factor = 1.0;
736 int bucket = insecure_rand.randrange(bucket_count);
745 node_id =
GetEntry(search_tried, bucket, position);
747 if (!networks.empty()) {
748 const auto it{mapInfo.find(node_id)};
749 if (
Assume(it != mapInfo.end()) && networks.contains(it->second.GetNetwork()))
break;
760 const auto it_found{mapInfo.find(node_id)};
761 assert(it_found != mapInfo.end());
762 const AddrInfo& info{it_found->second};
765 if (insecure_rand.randbits<30>() < chance_factor * info.GetChance() * (1 << 30)) {
766 LogDebug(
BCLog::ADDRMAN,
"Selected %s from %s\n", info.ToStringAddrPort(), search_tried ?
"tried" :
"new");
767 return {info, info.m_last_try};
771 chance_factor *= 1.2;
781 return vvTried[bucket][position];
785 return vvNew[bucket][position];
792std::vector<CAddress>
AddrManImpl::GetAddr_(
size_t max_addresses,
size_t max_pct, std::optional<Network> network,
const bool filtered)
const
797 size_t nNodes = vRandom.size();
799 max_pct = std::min(max_pct,
size_t{100});
800 nNodes = max_pct * nNodes / 100;
802 if (max_addresses != 0) {
803 nNodes = std::min(nNodes, max_addresses);
807 const auto now{Now<NodeSeconds>()};
808 std::vector<CAddress> addresses;
809 addresses.reserve(nNodes);
810 for (
unsigned int n = 0; n < vRandom.size(); n++) {
811 if (addresses.size() >= nNodes)
814 int nRndPos = insecure_rand.randrange(vRandom.size() - n) + n;
816 const auto it{mapInfo.find(vRandom[n])};
817 assert(it != mapInfo.end());
822 if (network != std::nullopt && ai.GetNetClass() != network)
continue;
825 if (ai.IsTerrible(now) && filtered)
continue;
827 addresses.push_back(ai);
838 std::vector<std::pair<AddrInfo, AddressPosition>> infos;
839 for (
int bucket = 0; bucket < bucket_count; ++bucket) {
849 infos.emplace_back(info, location);
870 const auto update_interval{20min};
871 if (time - info.
nTime > update_interval) {
899 bool erase_collision =
false;
902 if (!mapInfo.contains(id_new)) {
903 erase_collision =
true;
905 AddrInfo& info_new = mapInfo[id_new];
911 erase_collision =
true;
912 }
else if (vvTried[tried_bucket][tried_bucket_pos] != -1) {
915 nid_type id_old = vvTried[tried_bucket][tried_bucket_pos];
916 AddrInfo& info_old = mapInfo[id_old];
918 const auto current_time{Now<NodeSeconds>()};
922 erase_collision =
true;
930 Good_(info_new,
false, current_time);
931 erase_collision =
true;
938 Good_(info_new,
false, current_time);
939 erase_collision =
true;
942 Good_(info_new,
false, Now<NodeSeconds>());
943 erase_collision =
true;
947 if (erase_collision) {
968 if (!mapInfo.contains(id_new)) {
973 const AddrInfo& newInfo = mapInfo[id_new];
979 const AddrInfo& info_old = mapInfo[vvTried[tried_bucket][tried_bucket_pos]];
989 if (!addr_info)
return std::nullopt;
1010 if (!net.has_value()) {
1011 if (in_new.has_value()) {
1012 return *in_new ? nNew : nTried;
1014 return vRandom.size();
1017 if (
auto it = m_network_counts.find(*net); it != m_network_counts.end()) {
1018 auto net_count = it->second;
1019 if (in_new.has_value()) {
1020 return *in_new ? net_count.n_new : net_count.n_tried;
1022 return net_count.n_new + net_count.n_tried;
1038 LogError(
"ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i", err);
1050 std::unordered_set<nid_type> setTried;
1051 std::unordered_map<nid_type, int> mapNew;
1052 std::unordered_map<Network, NewTriedCount> local_counts;
1054 if (vRandom.size() != (
size_t)(nTried + nNew))
1057 for (
const auto& entry : mapInfo) {
1059 const AddrInfo& info = entry.second;
1061 if (!TicksSinceEpoch<std::chrono::seconds>(info.
m_last_success)) {
1076 const auto it{mapAddr.find(info)};
1077 if (it == mapAddr.end() || it->second != n) {
1090 if (setTried.size() != (
size_t)nTried)
1092 if (mapNew.size() != (
size_t)nNew)
1097 if (vvTried[n][i] != -1) {
1098 if (!setTried.contains(vvTried[n][i]))
1100 const auto it{mapInfo.find(vvTried[n][i])};
1101 if (it == mapInfo.end() || it->second.GetTriedBucket(
nKey,
m_netgroupman) != n) {
1104 if (it->second.GetBucketPosition(
nKey,
false, n) != i) {
1107 setTried.erase(vvTried[n][i]);
1114 if (vvNew[n][i] != -1) {
1115 if (!mapNew.contains(vvNew[n][i]))
1117 const auto it{mapInfo.find(vvNew[n][i])};
1118 if (it == mapInfo.end() || it->second.GetBucketPosition(
nKey,
true, n) != i) {
1121 if (--mapNew[vvNew[n][i]] == 0)
1122 mapNew.erase(vvNew[n][i]);
1127 if (setTried.size())
1136 if (m_network_counts.size() < local_counts.size()) {
1139 for (
const auto& [net,
count] : m_network_counts) {
1140 if (local_counts[net].n_new !=
count.n_new || local_counts[net].n_tried !=
count.n_tried) {
1170 auto ret =
Good_(addr,
true, time);
1179 Attempt_(addr, fCountFailure, time);
1200std::pair<CAddress, NodeSeconds>
AddrManImpl::Select(
bool new_only,
const std::unordered_set<Network>& networks)
const
1204 auto addrRet =
Select_(new_only, networks);
1209std::vector<CAddress>
AddrManImpl::GetAddr(
size_t max_addresses,
size_t max_pct, std::optional<Network> network,
const bool filtered)
const
1213 auto addresses =
GetAddr_(max_addresses, max_pct, network, filtered);
1253 : m_impl(
std::make_unique<
AddrManImpl>(netgroupman, deterministic, consistency_check_ratio)) {}
1257template <
typename Stream>
1260 m_impl->Serialize<Stream>(s_);
1263template <
typename Stream>
1266 m_impl->Unserialize<Stream>(s_);
1277size_t AddrMan::Size(std::optional<Network> net, std::optional<bool> in_new)
const
1279 return m_impl->Size(net, in_new);
1289 return m_impl->Good(addr, time);
1294 m_impl->Attempt(addr, fCountFailure, time);
1299 m_impl->ResolveCollisions();
1304 return m_impl->SelectTriedCollision();
1307std::pair<CAddress, NodeSeconds>
AddrMan::Select(
bool new_only,
const std::unordered_set<Network>& networks)
const
1309 return m_impl->Select(new_only, networks);
1312std::vector<CAddress>
AddrMan::GetAddr(
size_t max_addresses,
size_t max_pct, std::optional<Network> network,
const bool filtered)
const
1314 return m_impl->GetAddr(max_addresses, max_pct, network, filtered);
1319 return m_impl->GetEntries(use_tried);
1324 m_impl->Connected(addr, time);
1329 m_impl->SetServices(addr, nServices);
1334 return m_impl->FindAddressEntry(addr);
static constexpr uint32_t ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP
Over how many buckets entries with new addresses originating from a single group are spread.
static constexpr auto ADDRMAN_HORIZON
How old addresses can maximally be.
static constexpr int32_t ADDRMAN_MAX_FAILURES
How many successive failures are allowed ...
static constexpr auto ADDRMAN_MIN_FAIL
... in at least this duration
static constexpr auto ADDRMAN_TEST_WINDOW
The maximum time we'll spend trying to resolve a tried table collision.
static constexpr auto ADDRMAN_REPLACEMENT
How recent a successful connection should be before we allow an address to be evicted from tried.
static constexpr int32_t ADDRMAN_RETRIES
After how many failed attempts we give up on a new node.
static constexpr size_t ADDRMAN_SET_TRIED_COLLISION_SIZE
The maximum number of tried addr collisions to store.
static constexpr uint32_t ADDRMAN_TRIED_BUCKETS_PER_GROUP
Over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread.
static constexpr int32_t ADDRMAN_NEW_BUCKETS_PER_ADDRESS
Maximum number of times an address can occur in the new table.
static constexpr int ADDRMAN_TRIED_BUCKET_COUNT
static constexpr int ADDRMAN_BUCKET_SIZE
int64_t nid_type
User-defined type for the internally used nIds This used to be int, making it feasible for attackers ...
static constexpr int ADDRMAN_NEW_BUCKET_COUNT
#define Assume(val)
Assume is the identity function.
Extended statistics about a CAddress.
int GetNewBucket(const uint256 &nKey, const CNetAddr &src, const NetGroupManager &netgroupman) const
Calculate in which "new" bucket this entry belongs, given a certain source.
int GetTriedBucket(const uint256 &nKey, const NetGroupManager &netgroupman) const
Calculate in which "tried" bucket this entry belongs.
int nRandomPos
position in vRandom
int GetBucketPosition(const uint256 &nKey, bool fNew, int bucket) const
Calculate in which position of a bucket to store this entry.
bool fInTried
in tried set? (memory only)
NodeSeconds m_last_success
last successful connection by us
NodeSeconds m_last_count_attempt
last counted attempt (memory only)
NodeSeconds m_last_try
last try whatsoever by us (memory only)
double GetChance(NodeSeconds now=Now< NodeSeconds >()) const
Calculate the relative chance this entry should be given when selecting nodes to connect to.
bool IsTerrible(NodeSeconds now=Now< NodeSeconds >()) const
Determine whether the statistics about this entry are bad enough so that it can just be deleted.
int nRefCount
reference count in new sets (memory only)
int nAttempts
connection attempts since last successful attempt
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
std::pair< CAddress, NodeSeconds > Select(bool new_only=false, const std::unordered_set< Network > &networks={}) const
Choose an address to connect to.
const std::unique_ptr< AddrManImpl > m_impl
void Attempt(const CService &addr, bool fCountFailure, NodeSeconds time=Now< NodeSeconds >())
Mark an entry as connection attempted to.
size_t Size(std::optional< Network > net=std::nullopt, std::optional< bool > in_new=std::nullopt) const
Return size information about addrman.
std::optional< AddressPosition > FindAddressEntry(const CAddress &addr)
Test-only function Find the address record in AddrMan and return information about its position.
std::vector< std::pair< AddrInfo, AddressPosition > > GetEntries(bool from_tried) const
Returns an information-location pair for all addresses in the selected addrman table.
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const
Return all or many randomly selected addresses, optionally by network.
void ResolveCollisions()
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
bool Good(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
Mark an address record as accessible and attempt to move it to addrman's tried table.
void Serialize(Stream &s_) const
void Unserialize(Stream &s_)
AddrMan(const NetGroupManager &netgroupman, bool deterministic, int32_t consistency_check_ratio)
std::pair< CAddress, NodeSeconds > SelectTriedCollision()
Randomly select an address in the tried table that another address is attempting to evict.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs)
Clear a position in a "new" table. This is the only place where entries are actually deleted.
AddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, nid_type *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Create a new entry and add it to the internal data structures mapInfo, mapAddr and vRandom.
void Connected_(const CService &addr, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
void Attempt_(const CService &addr, bool fCountFailure, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
static constexpr Format FILE_FORMAT
The maximum format this software knows it can unserialize.
void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs)
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
void Serialize(Stream &s_) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
void Delete(nid_type nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
Delete an entry. It must not be in tried, and have refcount 0.
std::pair< CAddress, NodeSeconds > Select_(bool new_only, const std::unordered_set< Network > &networks) const EXCLUSIVE_LOCKS_REQUIRED(cs)
void Connected(const CService &addr, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(!cs)
void SetServices(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(!cs)
std::optional< AddressPosition > FindAddressEntry_(const CAddress &addr) EXCLUSIVE_LOCKS_REQUIRED(cs)
void MakeTried(AddrInfo &info, nid_type nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
Move an entry from the "new" table(s) to the "tried" table.
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs)
AddrInfo * Find(const CService &addr, nid_type *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Find an entry.
AddrManImpl(const NetGroupManager &netgroupman, bool deterministic, int32_t consistency_check_ratio)
std::vector< std::pair< AddrInfo, AddressPosition > > GetEntries(bool from_tried) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
const int32_t m_consistency_check_ratio
Perform consistency checks every m_consistency_check_ratio operations (if non-zero).
std::vector< std::pair< AddrInfo, AddressPosition > > GetEntries_(bool from_tried) const EXCLUSIVE_LOCKS_REQUIRED(cs)
void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Consistency check, taking into account m_consistency_check_ratio.
int CheckAddrman() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Perform consistency check, regardless of m_consistency_check_ratio.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(!cs)
std::optional< AddressPosition > FindAddressEntry(const CAddress &addr) EXCLUSIVE_LOCKS_REQUIRED(!cs)
bool Good_(const CService &addr, bool test_before_evict, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
std::vector< CAddress > GetAddr_(size_t max_addresses, size_t max_pct, std::optional< Network > network, bool filtered=true) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Mutex cs
A mutex to protect the inner data structures.
size_t Size_(std::optional< Network > net, std::optional< bool > in_new) const EXCLUSIVE_LOCKS_REQUIRED(cs)
std::pair< CAddress, NodeSeconds > SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs)
std::pair< CAddress, NodeSeconds > SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs)
std::set< nid_type > m_tried_collisions
Holds addrs inserted into tried table that collide with existing entries. Test-before-evict disciplin...
static constexpr uint8_t INCOMPATIBILITY_BASE
The initial value of a field that is incremented every time an incompatible format change is made (su...
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Swap two elements in vRandom.
std::pair< CAddress, NodeSeconds > Select(bool new_only, const std::unordered_set< Network > &networks) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
void Attempt(const CService &addr, bool fCountFailure, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(!cs)
void Unserialize(Stream &s_) EXCLUSIVE_LOCKS_REQUIRED(!cs)
nid_type GetEntry(bool use_tried, size_t bucket, size_t position) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Helper to generalize looking up an addrman entry from either table.
uint256 nKey
secret key to randomize bucket select with
void ResolveCollisions() EXCLUSIVE_LOCKS_REQUIRED(!cs)
const NetGroupManager & m_netgroupman
Reference to the netgroup manager.
bool Add_(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs)
bool Good(const CService &addr, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(!cs)
size_t Size(std::optional< Network > net, std::optional< bool > in_new) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
bool AddSingle(const CAddress &addr, const CNetAddr &source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs)
Attempt to add a single address to addrman's new table.
Non-refcounted RAII wrapper for FILE*.
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
static constexpr SerParams V1_DISK
static constexpr SerParams V2_DISK
enum Network GetNetwork() const
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringAddrPort() const
std::vector< unsigned char > GetKey() const
Double ended buffer combining vector and stream-like interfaces.
Reads data from an underlying stream, while hashing the read data.
A writer stream (for serialization) that computes a 256-bit hash.
Writes data to an underlying source stream, while hashing the written data.
uint256 GetAsmapVersion() const
Get the asmap version, a checksum identifying the asmap being used.
std::vector< unsigned char > GetGroup(const CNetAddr &address) const
Get the canonical identifier of the network group for address.
uint32_t GetMappedAS(const CNetAddr &address) const
Get the autonomous system on the BGP path to address.
Wrapper that overrides the GetParams() function of a stream.
constexpr bool IsNull() const
#define LogDebug(category,...)
ServiceFlags
nServices flags
Location information for an address in AddrMan.
static time_point now() noexcept
Return current system time or mocked time, if set.
#define LOG_TIME_MILLIS_WITH_CATEGORY_MSG_ONCE(end_msg, log_category)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds