Merge #6254: backport: merge bitcoin#25678, #26040, #26847, #25619, #27214, #26261, #27745, #27529, #28341, partial bitcoin#25331 (addrman backports: part 4)

e544d3c741 fmt: apply `clang-format-diff.py` suggestions, satisfy linter (Kittywhiskers Van Gogh)
7da74ffcd5 merge bitcoin#28341: Use HashWriter over legacy CHashWriter (Kittywhiskers Van Gogh)
c798b496cd merge bitcoin#27529: fix `feature_addrman.py` on big-endian systems (Kittywhiskers Van Gogh)
7d149c97be merge bitcoin#27745: select addresses by network follow-up (Kittywhiskers Van Gogh)
1d82994383 merge bitcoin#26261: cleanup `LookupIntern`, `Lookup` and `LookupHost` (Kittywhiskers Van Gogh)
231ff82c2e merge bitcoin#27214: Enable selecting addresses by network (Kittywhiskers Van Gogh)
e82559516c merge bitcoin#25619: avoid overriding non-virtual ToString() in CService and use better naming (Kittywhiskers Van Gogh)
2e9b48a910 merge bitcoin#26847: track AddrMan totals by network and table, improve precision of adding fixed seeds (Kittywhiskers Van Gogh)
79a550ec15 merge bitcoin#26040: comment "add only reachable addresses to addrman" (Kittywhiskers Van Gogh)
1adb635ec6 merge bitcoin#25678: skip querying dns seeds if -onlynet disables IPv4 and IPv6 (Kittywhiskers Van Gogh)
2d99be0aea partial bitcoin#25331: Add HashWriter without ser-type and ser-version (Kittywhiskers Van Gogh)

Pull request description:

  ## Additional Information

  * Dependent on https://github.com/dashpay/dash/pull/6243

  * Dependent on https://github.com/dashpay/dash/pull/5167

  ## Breaking Changes

  None observed.

  ## Checklist:

  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)**
  - [x] I have added or updated relevant unit/integration/functional/e2e tests
  - [x] I have made corresponding changes to the documentation **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  UdjinM6:
    utACK e544d3c741

Tree-SHA512: 63f014142c39c47bda3ac85dc6afeee8f2bfec71f033631bca16d41bb0785f4b090b3c860ddc3b3cf6c4a23558d3d102144fc83b065130c3f9ab91d0de8e4457
This commit is contained in:
pasta 2024-09-12 09:29:05 -05:00
commit 17110f50b3
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984
50 changed files with 915 additions and 613 deletions

View File

@ -192,7 +192,7 @@ std::optional<bilingual_str> LoadAddrman(const NetGroupManager& netgroupman, con
const auto path_addr{gArgs.GetDataDirNet() / "peers.dat"};
try {
DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->size(), GetTimeMillis() - nStart);
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->Size(), GetTimeMillis() - nStart);
} catch (const DbNotFoundError&) {
// Addrman can be in an inconsistent state after failure, reset it
addrman = std::make_unique<AddrMan>(netgroupman, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);

View File

@ -45,22 +45,22 @@ static constexpr int64_t ADDRMAN_TEST_WINDOW{40*60}; // 40 minutes
int AddrInfo::GetTriedBucket(const uint256& nKey, const NetGroupManager& netgroupman) const
{
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetKey()).GetCheapHash();
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << netgroupman.GetGroup(*this) << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP)).GetCheapHash();
uint64_t hash1 = (HashWriter{} << nKey << GetKey()).GetCheapHash();
uint64_t hash2 = (HashWriter{} << nKey << netgroupman.GetGroup(*this) << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP)).GetCheapHash();
return hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
}
int AddrInfo::GetNewBucket(const uint256& nKey, const CNetAddr& src, const NetGroupManager& netgroupman) const
{
std::vector<unsigned char> vchSourceGroupKey = netgroupman.GetGroup(src);
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << netgroupman.GetGroup(*this) << vchSourceGroupKey).GetCheapHash();
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetCheapHash();
uint64_t hash1 = (HashWriter{} << nKey << netgroupman.GetGroup(*this) << vchSourceGroupKey).GetCheapHash();
uint64_t hash2 = (HashWriter{} << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetCheapHash();
return hash2 % ADDRMAN_NEW_BUCKET_COUNT;
}
int AddrInfo::GetBucketPosition(const uint256& nKey, bool fNew, int nBucket) const
int AddrInfo::GetBucketPosition(const uint256& nKey, bool fNew, int bucket) const
{
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << (fNew ? uint8_t{'N'} : uint8_t{'K'}) << nBucket << GetKey()).GetCheapHash();
uint64_t hash1 = (HashWriter{} << nKey << (fNew ? uint8_t{'N'} : uint8_t{'K'}) << bucket << GetKey()).GetCheapHash();
return hash1 % ADDRMAN_BUCKET_SIZE;
}
@ -282,6 +282,7 @@ void AddrManImpl::Unserialize(Stream& s_)
mapAddr[info] = n;
info.nRandomPos = vRandom.size();
vRandom.push_back(n);
m_network_counts[info.GetNetwork()].n_new++;
}
nIdCount = nNew;
@ -301,6 +302,7 @@ void AddrManImpl::Unserialize(Stream& s_)
mapAddr[info] = nIdCount;
vvTried[nKBucket][nKBucketPos] = nIdCount;
nIdCount++;
m_network_counts[info.GetNetwork()].n_tried++;
} else {
nLost++;
}
@ -414,6 +416,8 @@ AddrInfo* AddrManImpl::Create(const CAddress& addr, const CNetAddr& addrSource,
mapAddr[addr] = nId;
mapInfo[nId].nRandomPos = vRandom.size();
vRandom.push_back(nId);
nNew++;
m_network_counts[addr.GetNetwork()].n_new++;
if (pnId)
*pnId = nId;
return &mapInfo[nId];
@ -453,6 +457,7 @@ void AddrManImpl::Delete(int nId)
assert(info.nRefCount == 0);
SwapRandom(info.nRandomPos, vRandom.size() - 1);
m_network_counts[info.GetNetwork()].n_new--;
vRandom.pop_back();
mapAddr.erase(info);
mapInfo.erase(nId);
@ -470,7 +475,7 @@ void AddrManImpl::ClearNew(int nUBucket, int nUBucketPos)
assert(infoDelete.nRefCount > 0);
infoDelete.nRefCount--;
vvNew[nUBucket][nUBucketPos] = -1;
LogPrint(BCLog::ADDRMAN, "Removed %s from new[%i][%i]\n", infoDelete.ToString(), nUBucket, nUBucketPos);
LogPrint(BCLog::ADDRMAN, "Removed %s from new[%i][%i]\n", infoDelete.ToStringAddrPort(), nUBucket, nUBucketPos);
if (infoDelete.nRefCount == 0) {
Delete(nIdDelete);
}
@ -493,6 +498,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
}
}
nNew--;
m_network_counts[info.GetNetwork()].n_new--;
assert(info.nRefCount == 0);
@ -511,6 +517,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
infoOld.fInTried = false;
vvTried[nKBucket][nKBucketPos] = -1;
nTried--;
m_network_counts[infoOld.GetNetwork()].n_tried--;
// find which new bucket it belongs to
int nUBucket = infoOld.GetNewBucket(nKey, m_netgroupman);
@ -522,14 +529,16 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
infoOld.nRefCount = 1;
vvNew[nUBucket][nUBucketPos] = nIdEvict;
nNew++;
m_network_counts[infoOld.GetNetwork()].n_new++;
LogPrint(BCLog::ADDRMAN, "Moved %s from tried[%i][%i] to new[%i][%i] to make space\n",
infoOld.ToString(), nKBucket, nKBucketPos, nUBucket, nUBucketPos);
infoOld.ToStringAddrPort(), nKBucket, nKBucketPos, nUBucket, nUBucketPos);
}
assert(vvTried[nKBucket][nKBucketPos] == -1);
vvTried[nKBucket][nKBucketPos] = nId;
nTried++;
info.fInTried = true;
m_network_counts[info.GetNetwork()].n_tried++;
}
bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
@ -580,7 +589,6 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
} else {
pinfo = Create(addr, source, &nId);
pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
nNew++;
}
int nUBucket = pinfo->GetNewBucket(nKey, source, m_netgroupman);
@ -599,7 +607,7 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
pinfo->nRefCount++;
vvNew[nUBucket][nUBucketPos] = nId;
LogPrint(BCLog::ADDRMAN, "Added %s mapped to AS%i to new[%i][%i]\n",
addr.ToString(), m_netgroupman.GetMappedAS(addr), nUBucket, nUBucketPos);
addr.ToStringAddrPort(), m_netgroupman.GetMappedAS(addr), nUBucket, nUBucketPos);
} else {
if (pinfo->nRefCount == 0) {
Delete(nId);
@ -651,8 +659,8 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
auto colliding_entry = mapInfo.find(vvTried[tried_bucket][tried_bucket_pos]);
if (fLogIPs) {
LogPrint(BCLog::ADDRMAN, "Collision with %s while attempting to move %s to tried table. Collisions=%d\n",
colliding_entry != mapInfo.end() ? colliding_entry->second.ToString() : "",
addr.ToString(),
colliding_entry != mapInfo.end() ? colliding_entry->second.ToStringAddrPort() : "",
addr.ToStringAddrPort(),
m_tried_collisions.size());
}
return false;
@ -661,7 +669,7 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
MakeTried(info, nId);
if (fLogIPs) {
LogPrint(BCLog::ADDRMAN, "Moved %s mapped to AS%i to tried[%i][%i]\n",
addr.ToString(), m_netgroupman.GetMappedAS(addr), tried_bucket, tried_bucket_pos);
addr.ToStringAddrPort(), m_netgroupman.GetMappedAS(addr), tried_bucket, tried_bucket_pos);
}
return true;
}
@ -674,7 +682,7 @@ bool AddrManImpl::Add_(const std::vector<CAddress> &vAddr, const CNetAddr& sourc
added += AddSingle(*it, source, nTimePenalty) ? 1 : 0;
}
if (added > 0) {
LogPrint(BCLog::ADDRMAN, "Added %i addresses (of %i) from %s: %i tried, %i new\n", added, vAddr.size(), source.ToString(), nTried, nNew);
LogPrint(BCLog::ADDRMAN, "Added %i addresses (of %i) from %s: %i tried, %i new\n", added, vAddr.size(), source.ToStringAddr(), nTried, nNew);
}
return added > 0;
}
@ -699,73 +707,97 @@ void AddrManImpl::Attempt_(const CService& addr, bool fCountFailure, int64_t nTi
}
}
std::pair<CAddress, int64_t> AddrManImpl::Select_(bool newOnly) const
std::pair<CAddress, int64_t> AddrManImpl::Select_(bool new_only, std::optional<Network> network) const
{
AssertLockHeld(cs);
if (vRandom.empty()) return {};
if (newOnly && nNew == 0) return {};
size_t new_count = nNew;
size_t tried_count = nTried;
// Use a 50% chance for choosing between tried and new table entries.
if (!newOnly &&
(nTried > 0 && (nNew == 0 || insecure_rand.randbool() == 0))) {
// use a tried node
double fChanceFactor = 1.0;
while (1) {
// Pick a tried bucket, and an initial position in that bucket.
int nKBucket = insecure_rand.randrange(ADDRMAN_TRIED_BUCKET_COUNT);
int nKBucketPos = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE);
// Iterate over the positions of that bucket, starting at the initial one,
// and looping around.
int i;
for (i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
if (vvTried[nKBucket][(nKBucketPos + i) % ADDRMAN_BUCKET_SIZE] != -1) break;
if (network.has_value()) {
auto it = m_network_counts.find(*network);
if (it == m_network_counts.end()) return {};
auto counts = it->second;
new_count = counts.n_new;
tried_count = counts.n_tried;
}
if (new_only && new_count == 0) return {};
if (new_count + tried_count == 0) return {};
// Decide if we are going to search the new or tried table
// If either option is viable, use a 50% chance to choose
bool search_tried;
if (new_only || tried_count == 0) {
search_tried = false;
} else if (new_count == 0) {
search_tried = true;
} else {
search_tried = insecure_rand.randbool();
}
const int bucket_count{search_tried ? ADDRMAN_TRIED_BUCKET_COUNT : ADDRMAN_NEW_BUCKET_COUNT};
// Loop through the addrman table until we find an appropriate entry
double chance_factor = 1.0;
while (1) {
// Pick a bucket, and an initial position in that bucket.
int bucket = insecure_rand.randrange(bucket_count);
int initial_position = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE);
// Iterate over the positions of that bucket, starting at the initial one,
// and looping around.
int i, position, node_id;
for (i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
position = (initial_position + i) % ADDRMAN_BUCKET_SIZE;
node_id = GetEntry(search_tried, bucket, position);
if (node_id != -1) {
if (network.has_value()) {
const auto it{mapInfo.find(node_id)};
if (Assume(it != mapInfo.end()) && it->second.GetNetwork() == *network) break;
} else {
break;
}
}
// If the bucket is entirely empty, start over with a (likely) different one.
if (i == ADDRMAN_BUCKET_SIZE) continue;
// Find the entry to return.
int nId = vvTried[nKBucket][(nKBucketPos + i) % ADDRMAN_BUCKET_SIZE];
const auto it_found{mapInfo.find(nId)};
assert(it_found != mapInfo.end());
const AddrInfo& info{it_found->second};
// With probability GetChance() * fChanceFactor, return the entry.
if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30)) {
LogPrint(BCLog::ADDRMAN, "Selected %s from tried\n", info.ToString());
return {info, info.nLastTry};
}
// Otherwise start over with a (likely) different bucket, and increased chance factor.
fChanceFactor *= 1.2;
}
// If the bucket is entirely empty, start over with a (likely) different one.
if (i == ADDRMAN_BUCKET_SIZE) continue;
// Find the entry to return.
const auto it_found{mapInfo.find(node_id)};
assert(it_found != mapInfo.end());
const AddrInfo& info{it_found->second};
// With probability GetChance() * chance_factor, return the entry.
if (insecure_rand.randbits(30) < chance_factor * info.GetChance() * (1 << 30)) {
LogPrint(BCLog::ADDRMAN, "Selected %s from %s\n", info.ToStringAddrPort(), search_tried ? "tried" : "new");
return {info, info.nLastTry};
}
// Otherwise start over with a (likely) different bucket, and increased chance factor.
chance_factor *= 1.2;
}
}
int AddrManImpl::GetEntry(bool use_tried, size_t bucket, size_t position) const
{
AssertLockHeld(cs);
if (use_tried) {
if (Assume(position < ADDRMAN_BUCKET_SIZE) && Assume(bucket < ADDRMAN_TRIED_BUCKET_COUNT)) {
return vvTried[bucket][position];
}
} else {
// use a new node
double fChanceFactor = 1.0;
while (1) {
// Pick a new bucket, and an initial position in that bucket.
int nUBucket = insecure_rand.randrange(ADDRMAN_NEW_BUCKET_COUNT);
int nUBucketPos = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE);
// Iterate over the positions of that bucket, starting at the initial one,
// and looping around.
int i;
for (i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
if (vvNew[nUBucket][(nUBucketPos + i) % ADDRMAN_BUCKET_SIZE] != -1) break;
}
// If the bucket is entirely empty, start over with a (likely) different one.
if (i == ADDRMAN_BUCKET_SIZE) continue;
// Find the entry to return.
int nId = vvNew[nUBucket][(nUBucketPos + i) % ADDRMAN_BUCKET_SIZE];
const auto it_found{mapInfo.find(nId)};
assert(it_found != mapInfo.end());
const AddrInfo& info{it_found->second};
// With probability GetChance() * fChanceFactor, return the entry.
if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30)) {
LogPrint(BCLog::ADDRMAN, "Selected %s from new\n", info.ToString());
return {info, info.nLastTry};
}
// Otherwise start over with a (likely) different bucket, and increased chance factor.
fChanceFactor *= 1.2;
if (Assume(position < ADDRMAN_BUCKET_SIZE) && Assume(bucket < ADDRMAN_NEW_BUCKET_COUNT)) {
return vvNew[bucket][position];
}
}
return -1;
}
std::vector<CAddress> AddrManImpl::GetAddr_(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
@ -886,7 +918,7 @@ void AddrManImpl::ResolveCollisions_()
// Give address at least 60 seconds to successfully connect
if (current_time - info_old.nLastTry > 60) {
LogPrint(BCLog::ADDRMAN, "Replacing %s with %s in tried table\n", info_old.ToString(), info_new.ToString());
LogPrint(BCLog::ADDRMAN, "Replacing %s with %s in tried table\n", info_old.ToStringAddrPort(), info_new.ToStringAddrPort());
// Replaces an existing address already in the tried table with the new address
Good_(info_new, false, current_time);
@ -896,7 +928,7 @@ void AddrManImpl::ResolveCollisions_()
// If the collision hasn't resolved in some reasonable amount of time,
// just evict the old entry -- we must not be able to
// connect to it for some reason.
LogPrint(BCLog::ADDRMAN, "Unable to test; replacing %s with %s in tried table anyway\n", info_old.ToString(), info_new.ToString());
LogPrint(BCLog::ADDRMAN, "Unable to test; replacing %s with %s in tried table anyway\n", info_old.ToStringAddrPort(), info_new.ToStringAddrPort());
Good_(info_new, false, current_time);
erase_collision = true;
}
@ -965,6 +997,28 @@ std::optional<AddressPosition> AddrManImpl::FindAddressEntry_(const CAddress& ad
}
}
size_t AddrManImpl::Size_(std::optional<Network> net, std::optional<bool> in_new) const
{
AssertLockHeld(cs);
if (!net.has_value()) {
if (in_new.has_value()) {
return *in_new ? nNew : nTried;
} else {
return vRandom.size();
}
}
if (auto it = m_network_counts.find(*net); it != m_network_counts.end()) {
auto net_count = it->second;
if (in_new.has_value()) {
return *in_new ? net_count.n_new : net_count.n_tried;
} else {
return net_count.n_new + net_count.n_tried;
}
}
return 0;
}
void AddrManImpl::Check() const
{
AssertLockHeld(cs);
@ -989,6 +1043,7 @@ int AddrManImpl::CheckAddrman() const
std::unordered_set<int> setTried;
std::unordered_map<int, int> mapNew;
std::unordered_map<Network, NewTriedCount> local_counts;
if (vRandom.size() != (size_t)(nTried + nNew))
return -7;
@ -1002,12 +1057,14 @@ int AddrManImpl::CheckAddrman() const
if (info.nRefCount)
return -2;
setTried.insert(n);
local_counts[info.GetNetwork()].n_tried++;
} else {
if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
return -3;
if (!info.nRefCount)
return -4;
mapNew[n] = info.nRefCount;
local_counts[info.GetNetwork()].n_new++;
}
const auto it{mapAddr.find(info)};
if (it == mapAddr.end() || it->second != n) {
@ -1065,13 +1122,27 @@ int AddrManImpl::CheckAddrman() const
if (nKey.IsNull())
return -16;
// It's possible that m_network_counts may have all-zero entries that local_counts
// doesn't have if addrs from a network were being added and then removed again in the past.
if (m_network_counts.size() < local_counts.size()) {
return -20;
}
for (const auto& [net, count] : m_network_counts) {
if (local_counts[net].n_new != count.n_new || local_counts[net].n_tried != count.n_tried) {
return -21;
}
}
return 0;
}
size_t AddrManImpl::size() const
size_t AddrManImpl::Size(std::optional<Network> net, std::optional<bool> in_new) const
{
LOCK(cs); // TODO: Cache this in an atomic to avoid this overhead
return vRandom.size();
LOCK(cs);
Check();
auto ret = Size_(net, in_new);
Check();
return ret;
}
bool AddrManImpl::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
@ -1117,11 +1188,11 @@ std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision()
return ret;
}
std::pair<CAddress, int64_t> AddrManImpl::Select(bool newOnly) const
std::pair<CAddress, int64_t> AddrManImpl::Select(bool new_only, std::optional<Network> network) const
{
LOCK(cs);
Check();
const auto addrRet = Select_(newOnly);
const auto addrRet = Select_(new_only, network);
Check();
return addrRet;
}
@ -1197,9 +1268,9 @@ template void AddrMan::Unserialize(CHashVerifier<CAutoFile>& s);
template void AddrMan::Unserialize(CDataStream& s);
template void AddrMan::Unserialize(CHashVerifier<CDataStream>& s);
size_t AddrMan::size() const
size_t AddrMan::Size(std::optional<Network> net, std::optional<bool> in_new) const
{
return m_impl->size();
return m_impl->Size(net, in_new);
}
bool AddrMan::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
@ -1227,9 +1298,9 @@ std::pair<CAddress, int64_t> AddrMan::SelectTriedCollision()
return m_impl->SelectTriedCollision();
}
std::pair<CAddress, int64_t> AddrMan::Select(bool newOnly) const
std::pair<CAddress, int64_t> AddrMan::Select(bool new_only, std::optional<Network> network) const
{
return m_impl->Select(newOnly);
return m_impl->Select(new_only, network);
}
std::vector<CAddress> AddrMan::GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const

View File

@ -110,8 +110,14 @@ public:
template <typename Stream>
void Unserialize(Stream& s_);
//! Return the number of (unique) addresses in all tables.
size_t size() const;
/**
* Return size information about addrman.
*
* @param[in] net Select addresses only from specified network (nullopt = all)
* @param[in] in_new Select addresses only from one table (true = new, false = tried, nullopt = both)
* @return Number of unique addresses that match specified options.
*/
size_t Size(std::optional<Network> net = {}, std::optional<bool> in_new = {}) const;
/**
* Attempt to add one or more addresses to addrman's new table.
@ -151,11 +157,16 @@ public:
/**
* Choose an address to connect to.
*
* @param[in] newOnly Whether to only select addresses from the new table.
* @param[in] new_only Whether to only select addresses from the new table. Passing `true` returns
* an address from the new table or an empty pair. Passing `false` will return an
* empty pair or an address from either the new or tried table (it does not
* guarantee a tried entry).
* @param[in] network Select only addresses of this network (nullopt = all). Passing a network may
* slow down the search.
* @return CAddress The record for the selected peer.
* int64_t The last time we attempted to connect to that peer.
*/
std::pair<CAddress, int64_t> Select(bool newOnly = false) const;
std::pair<CAddress, int64_t> Select(bool new_only = false, std::optional<Network> network = std::nullopt) const;
/**
* Return all or many randomly selected addresses, optionally by network.

View File

@ -88,7 +88,7 @@ public:
}
//! Calculate in which position of a bucket to store this entry.
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const;
int GetBucketPosition(const uint256 &nKey, bool fNew, int bucket) const;
//! Determine whether the statistics about this entry are bad enough so that it can just be deleted
bool IsTerrible(int64_t nNow = GetAdjustedTime()) const;
@ -110,7 +110,7 @@ public:
template <typename Stream>
void Unserialize(Stream& s_) EXCLUSIVE_LOCKS_REQUIRED(!cs);
size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
size_t Size(std::optional<Network> net, std::optional<bool> in_new) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
@ -125,7 +125,7 @@ public:
std::pair<CAddress, int64_t> SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs);
std::pair<CAddress, int64_t> Select(bool newOnly) const
std::pair<CAddress, int64_t> Select(bool new_only, std::optional<Network> network) const
EXCLUSIVE_LOCKS_REQUIRED(!cs);
std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
@ -216,6 +216,14 @@ private:
/** Reference to the netgroup manager. netgroupman must be constructed before addrman and destructed after. */
const NetGroupManager& m_netgroupman;
struct NewTriedCount {
size_t n_new;
size_t n_tried;
};
/** Number of entries in addrman per network and new/tried table. */
std::unordered_map<Network, NewTriedCount> m_network_counts GUARDED_BY(cs);
//! Find an entry.
AddrInfo* Find(const CService& addr, int* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
@ -244,7 +252,13 @@ private:
void Attempt_(const CService& addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
std::pair<CAddress, int64_t> Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs);
std::pair<CAddress, int64_t> Select_(bool new_only, std::optional<Network> network) const EXCLUSIVE_LOCKS_REQUIRED(cs);
/** Helper to generalize looking up an addrman entry from either table.
*
* @return int The nid of the entry. If the addrman position is empty or not found, returns -1.
* */
int GetEntry(bool use_tried, size_t bucket, size_t position) const EXCLUSIVE_LOCKS_REQUIRED(cs);
std::vector<CAddress> GetAddr_(size_t max_addresses, size_t max_pct, std::optional<Network> network) const EXCLUSIVE_LOCKS_REQUIRED(cs);
@ -260,6 +274,8 @@ private:
std::optional<AddressPosition> FindAddressEntry_(const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(cs);
size_t Size_(std::optional<Network> net, std::optional<bool> in_new) const EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Consistency check, taking into account m_consistency_check_ratio.
//! Will std::abort if an inconsistency is detected.
void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs);

View File

@ -4,6 +4,7 @@
#include <addrman.h>
#include <bench/bench.h>
#include <netbase.h>
#include <netgroup.h>
#include <random.h>
#include <util/time.h>
@ -93,6 +94,41 @@ static void AddrManSelect(benchmark::Bench& bench)
});
}
// The worst case performance of the Select() function is when there is only
// one address on the table, because it linearly searches every position of
// several buckets before identifying the correct bucket
static void AddrManSelectFromAlmostEmpty(benchmark::Bench& bench)
{
AddrMan addrman{EMPTY_NETGROUPMAN, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
// Add one address to the new table
CService addr = Lookup("250.3.1.1", 8333, false).value();
addrman.Add({CAddress(addr, NODE_NONE)}, addr);
bench.run([&] {
(void)addrman.Select();
});
}
static void AddrManSelectByNetwork(benchmark::Bench& bench)
{
AddrMan addrman{EMPTY_NETGROUPMAN, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
// add single I2P address to new table
CService i2p_service;
i2p_service.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p");
CAddress i2p_address(i2p_service, NODE_NONE);
i2p_address.nTime = GetAdjustedTime();
const CNetAddr source{LookupHost("252.2.2.2", false).value()};
addrman.Add({i2p_address}, source);
FillAddrMan(addrman);
bench.run([&] {
(void)addrman.Select(/*new_only=*/false, NET_I2P);
});
}
static void AddrManGetAddr(benchmark::Bench& bench)
{
AddrMan addrman{EMPTY_NETGROUPMAN, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
@ -133,5 +169,7 @@ static void AddrManAddThenGood(benchmark::Bench& bench)
BENCHMARK(AddrManAdd);
BENCHMARK(AddrManSelect);
BENCHMARK(AddrManSelectFromAlmostEmpty);
BENCHMARK(AddrManSelectByNetwork);
BENCHMARK(AddrManGetAddr);
BENCHMARK(AddrManAddThenGood);

View File

@ -106,7 +106,7 @@ PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CDataS
return clientman->TrySubmitDenominate(dmn->pdmnState->addr, this->connman);
})) {
LogPrint(BCLog::COINJOIN, "DSQUEUE -- CoinJoin queue (%s) is ready on masternode %s\n", dsq.ToString(),
dmn->pdmnState->addr.ToString());
dmn->pdmnState->addr.ToStringAddrPort());
return {};
} else {
int64_t nLastDsq = m_mn_metaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq();
@ -123,7 +123,7 @@ PeerMsgRet CCoinJoinClientQueueManager::ProcessDSQueue(const CNode& peer, CDataS
m_mn_metaman.AllowMixing(dmn->proTxHash);
LogPrint(BCLog::COINJOIN, "DSQUEUE -- new CoinJoin queue (%s) from masternode %s\n", dsq.ToString(),
dmn->pdmnState->addr.ToString());
dmn->pdmnState->addr.ToStringAddrPort());
m_walletman.ForAnyCJClientMan([&dsq](const std::unique_ptr<CCoinJoinClientManager>& clientman) {
return clientman->MarkAlreadyJoinedQueueAsTried(dsq);
@ -215,7 +215,8 @@ void CCoinJoinClientSession::ProcessMessage(CNode& peer, CChainState& active_cha
} else if (msg_type == NetMsgType::DSCOMPLETE) {
if (!mixingMasternode) return;
if (mixingMasternode->pdmnState->addr != peer.addr) {
WalletCJLogPrint(m_wallet, "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n", mixingMasternode->pdmnState->addr.ToString(), peer.addr.ToString());
WalletCJLogPrint(m_wallet, "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n",
mixingMasternode->pdmnState->addr.ToStringAddrPort(), peer.addr.ToStringAddrPort());
return;
}
@ -1112,7 +1113,9 @@ bool CCoinJoinClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized,
m_clientman.AddUsedMasternode(dsq.masternodeOutpoint);
if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) {
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::JoinExistingQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString());
WalletCJLogPrint(m_wallet, /* Continued */
"CCoinJoinClientSession::JoinExistingQueue -- skipping masternode connection, addr=%s\n",
dmn->pdmnState->addr.ToStringAddrPort());
continue;
}
@ -1122,8 +1125,11 @@ bool CCoinJoinClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized,
connman.AddPendingMasternode(dmn->proTxHash);
SetState(POOL_STATE_QUEUE);
nTimeLastSuccessfulStep = GetTime();
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::JoinExistingQueue -- pending connection (from queue): nSessionDenom: %d (%s), addr=%s\n",
nSessionDenom, CoinJoin::DenominationToString(nSessionDenom), dmn->pdmnState->addr.ToString());
WalletCJLogPrint(m_wallet, /* Continued */
"CCoinJoinClientSession::JoinExistingQueue -- pending connection (from queue): nSessionDenom: "
"%d (%s), addr=%s\n",
nSessionDenom, CoinJoin::DenominationToString(nSessionDenom),
dmn->pdmnState->addr.ToStringAddrPort());
strAutoDenomResult = _("Trying to connect…");
return true;
}
@ -1173,21 +1179,24 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon
int64_t nLastDsq = m_mn_metaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq();
int64_t nDsqThreshold = m_mn_metaman.GetDsqThreshold(dmn->proTxHash, nMnCount);
if (nLastDsq != 0 && nDsqThreshold > m_mn_metaman.GetDsqCount()) {
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- Too early to mix on this masternode!" /* Continued */
" masternode=%s addr=%s nLastDsq=%d nDsqThreshold=%d nDsqCount=%d\n",
dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToString(), nLastDsq,
nDsqThreshold, m_mn_metaman.GetDsqCount());
WalletCJLogPrint(m_wallet, /* Continued */
"CCoinJoinClientSession::StartNewQueue -- Too early to mix on this masternode!" /* Continued */
" masternode=%s addr=%s nLastDsq=%d nDsqThreshold=%d nDsqCount=%d\n",
dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort(), nLastDsq,
nDsqThreshold, m_mn_metaman.GetDsqCount());
nTries++;
continue;
}
if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) {
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString());
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- skipping masternode connection, addr=%s\n",
dmn->pdmnState->addr.ToStringAddrPort());
nTries++;
continue;
}
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n", nTries, dmn->pdmnState->addr.ToString());
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n",
nTries, dmn->pdmnState->addr.ToStringAddrPort());
// try to get a single random denom out of setAmounts
while (nSessionDenom == 0) {
@ -1203,8 +1212,9 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon
pendingDsaRequest = CPendingDsaRequest(dmn->pdmnState->addr, CCoinJoinAccept(nSessionDenom, txMyCollateral));
SetState(POOL_STATE_QUEUE);
nTimeLastSuccessfulStep = GetTime();
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::StartNewQueue -- pending connection, nSessionDenom: %d (%s), addr=%s\n",
nSessionDenom, CoinJoin::DenominationToString(nSessionDenom), dmn->pdmnState->addr.ToString());
WalletCJLogPrint( /* Continued */
m_wallet, "CCoinJoinClientSession::StartNewQueue -- pending connection, nSessionDenom: %d (%s), addr=%s\n",
nSessionDenom, CoinJoin::DenominationToString(nSessionDenom), dmn->pdmnState->addr.ToStringAddrPort());
strAutoDenomResult = _("Trying to connect…");
return true;
}
@ -1217,7 +1227,7 @@ bool CCoinJoinClientSession::ProcessPendingDsaRequest(CConnman& connman)
if (!pendingDsaRequest) return false;
bool fDone = connman.ForNode(pendingDsaRequest.GetAddr(), [this, &connman](CNode* pnode) {
WalletCJLogPrint(m_wallet, "-- processing dsa queue for addr=%s\n", pnode->addr.ToString());
WalletCJLogPrint(m_wallet, "-- processing dsa queue for addr=%s\n", pnode->addr.ToStringAddrPort());
nTimeLastSuccessfulStep = GetTime();
CNetMsgMaker msgMaker(pnode->GetCommonVersion());
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSACCEPT, pendingDsaRequest.GetDSA()));
@ -1227,7 +1237,8 @@ bool CCoinJoinClientSession::ProcessPendingDsaRequest(CConnman& connman)
if (fDone) {
pendingDsaRequest = CPendingDsaRequest();
} else if (pendingDsaRequest.IsExpired()) {
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- failed to connect to %s\n", __func__, pendingDsaRequest.GetAddr().ToString());
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::%s -- failed to connect to %s\n", __func__,
pendingDsaRequest.GetAddr().ToStringAddrPort());
WITH_LOCK(cs_coinjoin, SetNull());
}
@ -1824,7 +1835,8 @@ void CCoinJoinClientSession::RelayIn(const CCoinJoinEntry& entry, CConnman& conn
if (!mixingMasternode) return;
connman.ForNode(mixingMasternode->pdmnState->addr, [&entry, &connman, this](CNode* pnode) {
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::RelayIn -- found master, relaying message to %s\n", pnode->addr.ToString());
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::RelayIn -- found master, relaying message to %s\n",
pnode->addr.ToStringAddrPort());
CNetMsgMaker msgMaker(pnode->GetCommonVersion());
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSVIN, entry));
return true;
@ -1877,18 +1889,18 @@ void CCoinJoinClientSession::GetJsonInfo(UniValue& obj) const
if (mixingMasternode != nullptr) {
assert(mixingMasternode->pdmnState);
obj.pushKV("protxhash", mixingMasternode->proTxHash.ToString());
obj.pushKV("outpoint", mixingMasternode->collateralOutpoint.ToStringShort());
obj.pushKV("service", mixingMasternode->pdmnState->addr.ToString());
obj.pushKV("outpoint", mixingMasternode->collateralOutpoint.ToStringShort());
obj.pushKV("service", mixingMasternode->pdmnState->addr.ToStringAddrPort());
}
obj.pushKV("denomination", ValueFromAmount(CoinJoin::DenominationToAmount(nSessionDenom)));
obj.pushKV("state", GetStateString());
obj.pushKV("denomination", ValueFromAmount(CoinJoin::DenominationToAmount(nSessionDenom)));
obj.pushKV("state", GetStateString());
obj.pushKV("entries_count", GetEntriesCount());
}
void CCoinJoinClientManager::GetJsonInfo(UniValue& obj) const
{
assert(obj.isObject());
obj.pushKV("running", IsMixing());
obj.pushKV("running", IsMixing());
UniValue arrSessions(UniValue::VARR);
AssertLockNotHeld(cs_deqsessions);
@ -1900,7 +1912,7 @@ void CCoinJoinClientManager::GetJsonInfo(UniValue& obj) const
arrSessions.push_back(objSession);
}
}
obj.pushKV("sessions", arrSessions);
obj.pushKV("sessions", arrSessions);
}
void CoinJoinWalletManager::Add(CWallet& wallet)

View File

@ -86,7 +86,8 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv)
int64_t nDsqThreshold = m_mn_metaman.GetDsqThreshold(dmn->proTxHash, mnList.GetValidMNsCount());
if (nLastDsq != 0 && nDsqThreshold > m_mn_metaman.GetDsqCount()) {
if (fLogIPs) {
LogPrint(BCLog::COINJOIN, "DSACCEPT -- last dsq too recent, must wait: peer=%d, addr=%s\n", peer.GetId(), peer.addr.ToString());
LogPrint(BCLog::COINJOIN, "DSACCEPT -- last dsq too recent, must wait: peer=%d, addr=%s\n",
peer.GetId(), peer.addr.ToStringAddrPort());
} else {
LogPrint(BCLog::COINJOIN, "DSACCEPT -- last dsq too recent, must wait: peer=%d\n", peer.GetId());
}
@ -173,12 +174,14 @@ PeerMsgRet CCoinJoinServer::ProcessDSQUEUE(const CNode& peer, CDataStream& vRecv
LogPrint(BCLog::COINJOIN, "DSQUEUE -- nLastDsq: %d nDsqThreshold: %d nDsqCount: %d\n", nLastDsq, nDsqThreshold, m_mn_metaman.GetDsqCount());
//don't allow a few nodes to dominate the queuing process
if (nLastDsq != 0 && nDsqThreshold > m_mn_metaman.GetDsqCount()) {
LogPrint(BCLog::COINJOIN, "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->pdmnState->addr.ToString());
LogPrint(BCLog::COINJOIN, "DSQUEUE -- Masternode %s is sending too many dsq messages\n",
dmn->pdmnState->addr.ToStringAddrPort());
return {};
}
m_mn_metaman.AllowMixing(dmn->proTxHash);
LogPrint(BCLog::COINJOIN, "DSQUEUE -- new CoinJoin queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString());
LogPrint(BCLog::COINJOIN, "DSQUEUE -- new CoinJoin queue (%s) from masternode %s\n", dsq.ToString(),
dmn->pdmnState->addr.ToStringAddrPort());
TRY_LOCK(cs_vecqueue, lockRecv);
if (!lockRecv) return {};

View File

@ -465,7 +465,7 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn, bool fBumpTota
if (dmn->pdmnState->addr != CService() && !AddUniqueProperty(*dmn, dmn->pdmnState->addr)) {
mnUniquePropertyMap = mnUniquePropertyMapSaved;
throw(std::runtime_error(strprintf("%s: Can't add a masternode %s with a duplicate address=%s", __func__,
dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringIPPort())));
dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort())));
}
if (!AddUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) {
mnUniquePropertyMap = mnUniquePropertyMapSaved;
@ -506,7 +506,7 @@ void CDeterministicMNList::UpdateMN(const CDeterministicMN& oldDmn, const std::s
if (!UpdateUniqueProperty(*dmn, oldState->addr, pdmnState->addr)) {
mnUniquePropertyMap = mnUniquePropertyMapSaved;
throw(std::runtime_error(strprintf("%s: Can't update a masternode %s with a duplicate address=%s", __func__,
oldDmn.proTxHash.ToString(), pdmnState->addr.ToStringIPPort())));
oldDmn.proTxHash.ToString(), pdmnState->addr.ToStringAddrPort())));
}
if (!UpdateUniqueProperty(*dmn, oldState->keyIDOwner, pdmnState->keyIDOwner)) {
mnUniquePropertyMap = mnUniquePropertyMapSaved;
@ -566,7 +566,7 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash)
if (dmn->pdmnState->addr != CService() && !DeleteUniqueProperty(*dmn, dmn->pdmnState->addr)) {
mnUniquePropertyMap = mnUniquePropertyMapSaved;
throw(std::runtime_error(strprintf("%s: Can't delete a masternode %s with a address=%s", __func__,
proTxHash.ToString(), dmn->pdmnState->addr.ToStringIPPort())));
proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort())));
}
if (!DeleteUniqueProperty(*dmn, dmn->pdmnState->keyIDOwner)) {
mnUniquePropertyMap = mnUniquePropertyMapSaved;

View File

@ -25,10 +25,14 @@ std::string CDeterministicMNState::ToString() const
operatorPayoutAddress = EncodeDestination(dest);
}
return strprintf("CDeterministicMNState(nVersion=%d, nRegisteredHeight=%d, nLastPaidHeight=%d, nPoSePenalty=%d, nPoSeRevivedHeight=%d, nPoSeBanHeight=%d, nRevocationReason=%d, "
"ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, addr=%s, payoutAddress=%s, operatorPayoutAddress=%s)",
nVersion, nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight, nRevocationReason,
EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), addr.ToStringIPPort(), payoutAddress, operatorPayoutAddress);
return strprintf("CDeterministicMNState(nVersion=%d, nRegisteredHeight=%d, nLastPaidHeight=%d, nPoSePenalty=%d, "
"nPoSeRevivedHeight=%d, nPoSeBanHeight=%d, nRevocationReason=%d, "
"ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, addr=%s, payoutAddress=%s, "
"operatorPayoutAddress=%s)",
nVersion, nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight,
nRevocationReason, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(),
EncodeDestination(PKHash(keyIDVoting)), addr.ToStringAddrPort(), payoutAddress,
operatorPayoutAddress);
}
UniValue CDeterministicMNState::ToJson(MnType nType) const
@ -36,7 +40,7 @@ UniValue CDeterministicMNState::ToJson(MnType nType) const
UniValue obj;
obj.setObject();
obj.pushKV("version", nVersion);
obj.pushKV("service", addr.ToStringIPPort());
obj.pushKV("service", addr.ToStringAddrPort());
obj.pushKV("registeredHeight", nRegisteredHeight);
obj.pushKV("lastPaidHeight", nLastPaidHeight);
obj.pushKV("consecutivePayments", nConsecutivePayments);
@ -71,7 +75,7 @@ UniValue CDeterministicMNStateDiff::ToJson(MnType nType) const
obj.pushKV("version", state.nVersion);
}
if (fields & Field_addr) {
obj.pushKV("service", state.addr.ToStringIPPort());
obj.pushKV("service", state.addr.ToStringAddrPort());
}
if (fields & Field_nRegisteredHeight) {
obj.pushKV("registeredHeight", state.nRegisteredHeight);

View File

@ -87,8 +87,13 @@ std::string CProRegTx::ToString() const
payee = EncodeDestination(dest);
}
return strprintf("CProRegTx(nVersion=%d, nType=%d, collateralOutpoint=%s, addr=%s, nOperatorReward=%f, ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, scriptPayout=%s, platformNodeID=%s, platformP2PPort=%d, platformHTTPPort=%d)",
nVersion, ToUnderlying(nType), collateralOutpoint.ToStringShort(), addr.ToString(), (double)nOperatorReward / 100, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), payee, platformNodeID.ToString(), platformP2PPort, platformHTTPPort);
return strprintf("CProRegTx(nVersion=%d, nType=%d, collateralOutpoint=%s, addr=%s, nOperatorReward=%f, "
"ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, scriptPayout=%s, platformNodeID=%s, "
"platformP2PPort=%d, platformHTTPPort=%d)",
nVersion, ToUnderlying(nType), collateralOutpoint.ToStringShort(), addr.ToStringAddrPort(),
(double)nOperatorReward / 100, EncodeDestination(PKHash(keyIDOwner)), pubKeyOperator.ToString(),
EncodeDestination(PKHash(keyIDVoting)), payee, platformNodeID.ToString(), platformP2PPort,
platformHTTPPort);
}
bool CProUpServTx::IsTriviallyValid(bool is_basic_scheme_active, TxValidationState& state) const
@ -111,8 +116,10 @@ std::string CProUpServTx::ToString() const
payee = EncodeDestination(dest);
}
return strprintf("CProUpServTx(nVersion=%d, nType=%d, proTxHash=%s, addr=%s, operatorPayoutAddress=%s, platformNodeID=%s, platformP2PPort=%d, platformHTTPPort=%d)",
nVersion, ToUnderlying(nType), proTxHash.ToString(), addr.ToString(), payee, platformNodeID.ToString(), platformP2PPort, platformHTTPPort);
return strprintf("CProUpServTx(nVersion=%d, nType=%d, proTxHash=%s, addr=%s, operatorPayoutAddress=%s, "
"platformNodeID=%s, platformP2PPort=%d, platformHTTPPort=%d)",
nVersion, ToUnderlying(nType), proTxHash.ToString(), addr.ToStringAddrPort(), payee,
platformNodeID.ToString(), platformP2PPort, platformHTTPPort);
}
bool CProUpRegTx::IsTriviallyValid(bool is_basic_scheme_active, TxValidationState& state) const

View File

@ -96,7 +96,7 @@ public:
obj.pushKV("type", ToUnderlying(nType));
obj.pushKV("collateralHash", collateralOutpoint.hash.ToString());
obj.pushKV("collateralIndex", (int)collateralOutpoint.n);
obj.pushKV("service", addr.ToString());
obj.pushKV("service", addr.ToStringAddrPort());
obj.pushKV("ownerAddress", EncodeDestination(PKHash(keyIDOwner)));
obj.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting)));
@ -181,7 +181,7 @@ public:
obj.pushKV("version", nVersion);
obj.pushKV("type", ToUnderlying(nType));
obj.pushKV("proTxHash", proTxHash.ToString());
obj.pushKV("service", addr.ToString());
obj.pushKV("service", addr.ToStringAddrPort());
if (CTxDestination dest; ExtractDestination(scriptOperatorPayout, dest)) {
obj.pushKV("operatorPayoutAddress", EncodeDestination(dest));
}

View File

@ -62,8 +62,12 @@ std::string CSimplifiedMNListEntry::ToString() const
operatorPayoutAddress = EncodeDestination(dest);
}
return strprintf("CSimplifiedMNListEntry(nVersion=%d, nType=%d, proRegTxHash=%s, confirmedHash=%s, service=%s, pubKeyOperator=%s, votingAddress=%s, isValid=%d, payoutAddress=%s, operatorPayoutAddress=%s, platformHTTPPort=%d, platformNodeID=%s)",
nVersion, ToUnderlying(nType), proRegTxHash.ToString(), confirmedHash.ToString(), service.ToString(), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)), isValid, payoutAddress, operatorPayoutAddress, platformHTTPPort, platformNodeID.ToString());
return strprintf("CSimplifiedMNListEntry(nVersion=%d, nType=%d, proRegTxHash=%s, confirmedHash=%s, service=%s, "
"pubKeyOperator=%s, votingAddress=%s, isValid=%d, payoutAddress=%s, operatorPayoutAddress=%s, "
"platformHTTPPort=%d, platformNodeID=%s)",
nVersion, ToUnderlying(nType), proRegTxHash.ToString(), confirmedHash.ToString(),
service.ToStringAddrPort(), pubKeyOperator.ToString(), EncodeDestination(PKHash(keyIDVoting)),
isValid, payoutAddress, operatorPayoutAddress, platformHTTPPort, platformNodeID.ToString());
}
UniValue CSimplifiedMNListEntry::ToJson(bool extended) const
@ -74,7 +78,7 @@ UniValue CSimplifiedMNListEntry::ToJson(bool extended) const
obj.pushKV("nType", ToUnderlying(nType));
obj.pushKV("proRegTxHash", proRegTxHash.ToString());
obj.pushKV("confirmedHash", confirmedHash.ToString());
obj.pushKV("service", service.ToString());
obj.pushKV("service", service.ToStringAddrPort());
obj.pushKV("pubKeyOperator", pubKeyOperator.ToString());
obj.pushKV("votingAddress", EncodeDestination(PKHash(keyIDVoting)));
obj.pushKV("isValid", isValid);

View File

@ -110,20 +110,12 @@ inline uint160 Hash160(const T1& in1)
}
/** A writer stream (for serialization) that computes a 256-bit hash. */
class CHashWriter
class HashWriter
{
private:
CSHA256 ctx;
const int nType;
const int nVersion;
public:
CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {}
int GetType() const { return nType; }
int GetVersion() const { return nVersion; }
void write(Span<const std::byte> src)
{
ctx.Write(UCharCast(src.data()), src.size());
@ -158,6 +150,26 @@ public:
return ReadLE64(result.begin());
}
template <typename T>
HashWriter& operator<<(const T& obj)
{
::Serialize(*this, obj);
return *this;
}
};
class CHashWriter : public HashWriter
{
private:
const int nType;
const int nVersion;
public:
CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {}
int GetType() const { return nType; }
int GetVersion() const { return nVersion; }
template<typename T>
CHashWriter& operator<<(const T& obj) {
// Serialize to this stream

View File

@ -203,7 +203,7 @@ static bool HTTPReq_JSONRPC(const CoreContext& context, HTTPRequest* req)
JSONRPCRequest jreq;
jreq.context = context;
jreq.peerAddr = req->GetPeer().ToString();
jreq.peerAddr = req->GetPeer().ToStringAddrPort();
if (!RPCAuthorized(authHeader.second, rpcRequest.user)) {
LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", jreq.peerAddr);

View File

@ -176,12 +176,8 @@ static bool ClientAllowed(const CNetAddr& netaddr)
static bool InitHTTPAllowList()
{
rpc_allow_subnets.clear();
CNetAddr localv4;
CNetAddr localv6;
LookupHost("127.0.0.1", localv4, false);
LookupHost("::1", localv6, false);
rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet
rpc_allow_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost
rpc_allow_subnets.push_back(CSubNet{LookupHost("127.0.0.1", false).value(), 8}); // always allow IPv4 local subnet
rpc_allow_subnets.push_back(CSubNet{LookupHost("::1", false).value()}); // always allow IPv6 localhost
for (const std::string& strAllow : gArgs.GetArgs("-rpcallowip")) {
CSubNet subnet;
LookupSubNet(strAllow, subnet);
@ -236,7 +232,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
// Early address-based allow check
if (!ClientAllowed(hreq->GetPeer())) {
LogPrint(BCLog::HTTP, "HTTP request from %s rejected: Client network is not allowed RPC access\n",
hreq->GetPeer().ToString());
hreq->GetPeer().ToStringAddrPort());
hreq->WriteReply(HTTP_FORBIDDEN);
return;
}
@ -244,13 +240,13 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
// Early reject unknown HTTP methods
if (hreq->GetRequestMethod() == HTTPRequest::UNKNOWN) {
LogPrint(BCLog::HTTP, "HTTP request from %s rejected: Unknown HTTP request method\n",
hreq->GetPeer().ToString());
hreq->GetPeer().ToStringAddrPort());
hreq->WriteReply(HTTP_BAD_METHOD);
return;
}
LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n",
RequestMethodString(hreq->GetRequestMethod()), SanitizeString(hreq->GetURI(), SAFE_CHARS_URI).substr(0, 100), hreq->GetPeer().ToString());
RequestMethodString(hreq->GetRequestMethod()), SanitizeString(hreq->GetURI(), SAFE_CHARS_URI).substr(0, 100), hreq->GetPeer().ToStringAddrPort());
// Find registered handler for prefix
std::string strURI = hreq->GetURI();
@ -357,8 +353,8 @@ static bool HTTPBindAddresses(struct evhttp* http)
LogPrintf("Binding RPC on address %s port %i\n", i->first, i->second);
evhttp_bound_socket *bind_handle = evhttp_bind_socket_with_handle(http, i->first.empty() ? nullptr : i->first.c_str(), i->second);
if (bind_handle) {
CNetAddr addr;
if (i->first.empty() || (LookupHost(i->first, addr, false) && addr.IsBindAny())) {
const std::optional<CNetAddr> addr{LookupHost(i->first, false)};
if (i->first.empty() || (addr.has_value() && addr->IsBindAny())) {
LogPrintf("WARNING: the RPC server is not safe to expose to untrusted networks such as the public internet\n");
}
boundSockets.push_back(bind_handle);

View File

@ -206,7 +206,7 @@ bool Session::Connect(const CService& to, Connection& conn, bool& proxy_error)
}
const Reply& lookup_reply =
SendRequestAndGetReply(*sock, strprintf("NAMING LOOKUP NAME=%s", to.ToStringIP()));
SendRequestAndGetReply(*sock, strprintf("NAMING LOOKUP NAME=%s", to.ToStringAddr()));
const std::string& dest = lookup_reply.Get("VALUE");
@ -233,7 +233,7 @@ bool Session::Connect(const CService& to, Connection& conn, bool& proxy_error)
throw std::runtime_error(strprintf("\"%s\"", connect_reply.full));
} catch (const std::runtime_error& e) {
Log("Error connecting to %s: %s", to.ToString(), e.what());
Log("Error connecting to %s: %s", to.ToStringAddrPort(), e.what());
CheckControlSock();
return false;
}
@ -302,7 +302,7 @@ std::unique_ptr<Sock> Session::Hello() const
}
if (!ConnectSocketDirectly(m_control_host, *sock, nConnectTimeout, true)) {
throw std::runtime_error(strprintf("Cannot connect to %s", m_control_host.ToString()));
throw std::runtime_error(strprintf("Cannot connect to %s", m_control_host.ToStringAddrPort()));
}
SendRequestAndGetReply(*sock, "HELLO VERSION MIN=3.1 MAX=3.1");
@ -371,7 +371,7 @@ void Session::CreateIfNotCreatedAlready()
const auto session_type = m_transient ? "transient" : "persistent";
const auto session_id = GetRandHash().GetHex().substr(0, 10); // full is overkill, too verbose in the logs
Log("Creating %s SAM session %s with %s", session_type, session_id, m_control_host.ToString());
Log("Creating %s SAM session %s with %s", session_type, session_id, m_control_host.ToStringAddrPort());
auto sock = Hello();
@ -411,7 +411,7 @@ void Session::CreateIfNotCreatedAlready()
Log("%s SAM session %s created, my address=%s",
Capitalize(session_type),
m_session_id,
m_my_addr.ToString());
m_my_addr.ToStringAddrPort());
}
std::unique_ptr<Sock> Session::StreamAccept()

View File

@ -973,6 +973,17 @@ void InitParameterInteraction(ArgsManager& args)
LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n", __func__);
}
if (args.IsArgSet("-onlynet")) {
const auto onlynets = args.GetArgs("-onlynet");
bool clearnet_reachable = std::any_of(onlynets.begin(), onlynets.end(), [](const auto& net) {
const auto n = ParseNetwork(net);
return n == NET_IPV4 || n == NET_IPV6;
});
if (!clearnet_reachable && args.SoftSetBoolArg("-dnsseed", false)) {
LogPrintf("%s: parameter interaction: -onlynet excludes IPv4 and IPv6 -> setting -dnsseed=0\n", __func__);
}
}
int64_t nPruneArg = args.GetArg("-prune", 0);
if (nPruneArg > 0) {
if (args.SoftSetBoolArg("-disablegovernance", true)) {
@ -1555,7 +1566,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
InitError(strprintf(_("Could not parse asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));
return false;
}
const uint256 asmap_version = SerializeHash(asmap);
const uint256 asmap_version = (HashWriter{} << asmap).GetHash();
LogPrintf("Using asmap version %s for IP bucketing\n", asmap_version.ToString());
} else {
LogPrintf("Using /16 prefix for IP bucketing\n");
@ -1678,6 +1689,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// 2.1. -onlynet is not given or
// 2.2. -onlynet=cjdns is given
// Requesting DNS seeds entails connecting to IPv4/IPv6, which -onlynet options may prohibit:
// If -dnsseed=1 is explicitly specified, abort. If it's left unspecified by the user, we skip
// the DNS seeds by adjusting -dnsseed in InitParameterInteraction.
if (args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED) == true && !IsReachable(NET_IPV4) && !IsReachable(NET_IPV6)) {
return InitError(strprintf(_("Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")));
};
// Check for host lookup allowed before parsing any network related parameters
fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
@ -1688,12 +1706,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
std::string proxyArg = args.GetArg("-proxy", "");
if (proxyArg != "" && proxyArg != "0") {
CService proxyAddr;
if (!Lookup(proxyArg, proxyAddr, 9050, fNameLookup)) {
const std::optional<CService> proxyAddr{Lookup(proxyArg, 9050, fNameLookup)};
if (!proxyAddr.has_value()) {
return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxyArg));
}
Proxy addrProxy = Proxy(proxyAddr, proxyRandomize);
Proxy addrProxy = Proxy(proxyAddr.value(), proxyRandomize);
if (!addrProxy.IsValid())
return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxyArg));
@ -1719,11 +1737,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
"reaching the Tor network is explicitly forbidden: -onion=0"));
}
} else {
CService addr;
if (!Lookup(onionArg, addr, 9050, fNameLookup) || !addr.IsValid()) {
const std::optional<CService> addr{Lookup(onionArg, 9050, fNameLookup)};
if (!addr.has_value() || !addr->IsValid()) {
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
}
onion_proxy = Proxy{addr, proxyRandomize};
onion_proxy = Proxy{addr.value(), proxyRandomize};
}
}
@ -1743,9 +1761,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
for (const std::string& strAddr : args.GetArgs("-externalip")) {
CService addrLocal;
if (Lookup(strAddr, addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid())
AddLocal(addrLocal, LOCAL_MANUAL);
const std::optional<CService> addrLocal{Lookup(strAddr, GetListenPort(), fNameLookup)};
if (addrLocal.has_value() && addrLocal->IsValid())
AddLocal(addrLocal.value(), LOCAL_MANUAL);
else
return InitError(ResolveErrMsg("externalip", strAddr));
}
@ -2379,19 +2397,21 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
static_cast<uint16_t>(args.GetArg("-port", Params().GetDefaultPort()));
for (const std::string& bind_arg : args.GetArgs("-bind")) {
CService bind_addr;
std::optional<CService> bind_addr;
const size_t index = bind_arg.rfind('=');
if (index == std::string::npos) {
if (Lookup(bind_arg, bind_addr, default_bind_port, /*fAllowLookup=*/false)) {
connOptions.vBinds.push_back(bind_addr);
bind_addr = Lookup(bind_arg, default_bind_port, /*fAllowLookup=*/false);
if (bind_addr.has_value()) {
connOptions.vBinds.push_back(bind_addr.value());
continue;
}
} else {
const std::string network_type = bind_arg.substr(index + 1);
if (network_type == "onion") {
const std::string truncated_bind_arg = bind_arg.substr(0, index);
if (Lookup(truncated_bind_arg, bind_addr, BaseParams().OnionServiceTargetPort(), false)) {
connOptions.onion_binds.push_back(bind_addr);
bind_addr = Lookup(truncated_bind_arg, BaseParams().OnionServiceTargetPort(), false);
if (bind_addr.has_value()) {
connOptions.onion_binds.push_back(bind_addr.value());
continue;
}
}
@ -2422,7 +2442,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
if (connOptions.onion_binds.size() > 1) {
InitWarning(strprintf(_("More than one onion bind address is provided. Using %s "
"for the automatically created Tor onion service."),
onion_service_target.ToStringIPPort()));
onion_service_target.ToStringAddrPort()));
}
StartTorControl(onion_service_target);
}
@ -2467,11 +2487,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
const std::string& i2psam_arg = args.GetArg("-i2psam", "");
if (!i2psam_arg.empty()) {
CService addr;
if (!Lookup(i2psam_arg, addr, 7656, fNameLookup) || !addr.IsValid()) {
const std::optional<CService> addr{Lookup(i2psam_arg, 7656, fNameLookup)};
if (!addr.has_value() || !addr->IsValid()) {
return InitError(strprintf(_("Invalid -i2psam address or hostname: '%s'"), i2psam_arg));
}
SetProxy(NET_I2P, Proxy{addr});
SetProxy(NET_I2P, Proxy{addr.value()});
} else {
SetReachable(NET_I2P, false);
}

View File

@ -795,7 +795,7 @@ bool EnsureQuorumConnections(const Consensus::LLMQParams& llmqParams, CConnman&
if (!dmn) {
debugMsg += strprintf(" %s (not in valid MN set anymore)\n", c.ToString());
} else {
debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToString());
debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToStringAddrPort());
}
}
LogPrint(BCLog::NET_NETCONN, debugMsg.c_str()); /* Continued */
@ -842,7 +842,7 @@ void AddQuorumProbeConnections(const Consensus::LLMQParams& llmqParams, CConnman
if (!dmn) {
debugMsg += strprintf(" %s (not in valid MN set anymore)\n", c.ToString());
} else {
debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToString());
debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToStringAddrPort());
}
}
LogPrint(BCLog::NET_NETCONN, debugMsg.c_str()); /* Continued */

View File

@ -103,7 +103,7 @@ static bool NatpmpMapping(natpmp_t* natpmp, const struct in_addr& external_ipv4_
AddLocal(external, LOCAL_MAPPED);
external_ip_discovered = true;
}
LogPrintf("natpmp: Port mapping successful. External address = %s\n", external.ToString());
LogPrintf("natpmp: Port mapping successful. External address = %s\n", external.ToStringAddrPort());
return true;
} else {
LogPrintf("natpmp: Port mapping failed.\n");
@ -178,10 +178,10 @@ static bool ProcessUpnp()
LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
} else {
if (externalIPAddress[0]) {
CNetAddr resolved;
if (LookupHost(externalIPAddress, resolved, false)) {
LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString());
AddLocal(resolved, LOCAL_MAPPED);
std::optional<CNetAddr> resolved{LookupHost(externalIPAddress, false)};
if (resolved.has_value()) {
LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved->ToStringAddr());
AddLocal(resolved.value(), LOCAL_MAPPED);
}
} else {
LogPrintf("UPnP: GetExternalIPAddress failed.\n");

View File

@ -118,11 +118,11 @@ void CActiveMasternodeManager::InitInternal(const CBlockIndex* pindex)
}
// Check socket connectivity
LogPrintf("CActiveMasternodeManager::Init -- Checking inbound connection to '%s'\n", m_info.service.ToString());
LogPrintf("CActiveMasternodeManager::Init -- Checking inbound connection to '%s'\n", m_info.service.ToStringAddrPort());
std::unique_ptr<Sock> sock = CreateSock(m_info.service);
if (!sock) {
m_state = MASTERNODE_ERROR;
m_error = "Could not create socket to connect to " + m_info.service.ToString();
m_error = "Could not create socket to connect to " + m_info.service.ToStringAddrPort();
LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error);
return;
}
@ -131,7 +131,7 @@ void CActiveMasternodeManager::InitInternal(const CBlockIndex* pindex)
if (!fConnected && Params().RequireRoutableExternalIP()) {
m_state = MASTERNODE_ERROR;
m_error = "Could not connect to " + m_info.service.ToString();
m_error = "Could not connect to " + m_info.service.ToStringAddrPort();
LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", m_error);
return;
}
@ -188,13 +188,13 @@ bool CActiveMasternodeManager::GetLocalAddress(CService& addrRet)
// Addresses could be specified via externalip or bind option, discovered via UPnP
// or added by TorController. Use some random dummy IPv4 peer to prefer the one
// reachable via IPv4.
CNetAddr addrDummyPeer;
bool fFoundLocal{false};
if (LookupHost("8.8.8.8", addrDummyPeer, false)) {
fFoundLocal = GetLocal(addrRet, &addrDummyPeer) && IsValidNetAddr(addrRet);
if (auto peerAddr = LookupHost("8.8.8.8", false); peerAddr.has_value()) {
fFoundLocal = GetLocal(addrRet, &peerAddr.value()) && IsValidNetAddr(addrRet);
}
if (!fFoundLocal && !Params().RequireRoutableExternalIP()) {
if (Lookup("127.0.0.1", addrRet, GetListenPort(), false)) {
if (auto addr = Lookup("127.0.0.1", GetListenPort(), false); addr.has_value()) {
addrRet = addr.value();
fFoundLocal = true;
}
}

View File

@ -81,7 +81,8 @@ void CMasternodeUtils::DoMaintenance(CConnman& connman, CDeterministicMNManager&
if (fFound) return; // do NOT disconnect mixing masternodes
#endif // ENABLE_WALLET
if (fLogIPs) {
LogPrint(BCLog::NET_NETCONN, "Closing Masternode connection: peer=%d, addr=%s\n", pnode->GetId(), pnode->addr.ToString());
LogPrint(BCLog::NET_NETCONN, "Closing Masternode connection: peer=%d, addr=%s\n", pnode->GetId(),
pnode->addr.ToStringAddrPort());
} else {
LogPrint(BCLog::NET_NETCONN, "Closing Masternode connection: peer=%d\n", pnode->GetId());
}

View File

@ -162,14 +162,10 @@ uint16_t GetListenPort()
{
// If -bind= is provided with ":port" part, use that (first one if multiple are provided).
for (const std::string& bind_arg : gArgs.GetArgs("-bind")) {
CService bind_addr;
constexpr uint16_t dummy_port = 0;
if (Lookup(bind_arg, bind_addr, dummy_port, /*fAllowLookup=*/false)) {
if (bind_addr.GetPort() != dummy_port) {
return bind_addr.GetPort();
}
}
const std::optional<CService> bind_addr{Lookup(bind_arg, dummy_port, /*fAllowLookup=*/false)};
if (bind_addr.has_value() && bind_addr->GetPort() != dummy_port) return bind_addr->GetPort();
}
// Otherwise, if -whitebind= without NetPermissionFlags::NoBan is provided, use that
@ -229,7 +225,7 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
s >> endpoint;
CAddress addr{endpoint, GetDesirableServiceFlags(NODE_NONE)};
addr.nTime = GetTime() - rng.randrange(nOneWeek) - nOneWeek;
LogPrint(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToString());
LogPrint(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToStringAddrPort());
vSeedsOut.push_back(addr);
}
return vSeedsOut;
@ -288,7 +284,7 @@ std::optional<CService> GetLocalAddrForPeer(CNode& node)
}
if (addrLocal.IsRoutable())
{
LogPrint(BCLog::NET, "Advertising address %s to peer=%d\n", addrLocal.ToString(), node.GetId());
LogPrint(BCLog::NET, "Advertising address %s to peer=%d\n", addrLocal.ToStringAddrPort(), node.GetId());
return addrLocal;
}
// Address is unroutable. Don't advertise.
@ -325,7 +321,7 @@ bool AddLocal(const CService& addr_, int nScore)
if (!IsReachable(addr))
return false;
LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore);
LogPrintf("AddLocal(%s,%i)\n", addr.ToStringAddrPort(), nScore);
{
LOCK(g_maplocalhost_mutex);
@ -348,7 +344,7 @@ bool AddLocal(const CNetAddr &addr, int nScore)
void RemoveLocal(const CService& addr)
{
LOCK(g_maplocalhost_mutex);
LogPrintf("RemoveLocal(%s)\n", addr.ToString());
LogPrintf("RemoveLocal(%s)\n", addr.ToStringAddrPort());
mapLocalHost.erase(addr);
}
@ -447,7 +443,7 @@ CNode* CConnman::FindNode(const CService& addr, bool fExcludeDisconnecting)
bool CConnman::AlreadyConnectedToAddress(const CAddress& addr)
{
return FindNode(addr.ToStringIPPort());
return FindNode(addr.ToStringAddrPort());
}
bool CConnman::CheckIncomingNonce(uint64_t nonce)
@ -499,7 +495,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
/// debug print
if (fLogIPs) {
LogPrint(BCLog::NET, "trying connection %s lastseen=%.1fhrs\n",
pszDest ? pszDest : addrConnect.ToString(),
pszDest ? pszDest : addrConnect.ToStringAddrPort(),
pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
} else {
LogPrint(BCLog::NET, "trying connection lastseen=%.1fhrs\n",
@ -510,12 +506,12 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
const uint16_t default_port{pszDest != nullptr ? Params().GetDefaultPort(pszDest) :
Params().GetDefaultPort()};
if (pszDest) {
std::vector<CService> resolved;
if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
const CService rnd{resolved[GetRand(resolved.size())]};
const std::vector<CService> resolved{Lookup(pszDest, default_port, fNameLookup && !HaveNameProxy(), 256)};
if (!resolved.empty()) {
const CService& rnd{resolved[GetRand(resolved.size())]};
addrConnect = CAddress{MaybeFlipIPv6toCJDNS(rnd), NODE_NONE};
if (!addrConnect.IsValid()) {
LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToStringAddrPort(), pszDest);
return nullptr;
}
// It is possible that we already have a connection to the IP/port pszDest resolved to.
@ -575,7 +571,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
if (!sock) {
return nullptr;
}
connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(),
connected = ConnectThroughProxy(proxy, addrConnect.ToStringAddr(), addrConnect.GetPort(),
*sock, nConnectTimeout, proxyConnectionFailed);
} else {
// no proxy needed (none set for target network)
@ -714,7 +710,7 @@ void CNode::SetAddrLocal(const CService& addrLocalIn) {
AssertLockNotHeld(m_addr_local_mutex);
LOCK(m_addr_local_mutex);
if (addrLocal.IsValid()) {
error("Addr local already set for node: %i. Refusing to change from %s to %s", id, addrLocal.ToString(), addrLocalIn.ToString());
error("Addr local already set for node: %i. Refusing to change from %s to %s", id, addrLocal.ToStringAddrPort(), addrLocalIn.ToStringAddrPort());
} else {
addrLocal = addrLocalIn;
}
@ -722,7 +718,7 @@ void CNode::SetAddrLocal(const CService& addrLocalIn) {
std::string CNode::GetLogString() const
{
return fLogIPs ? addr.ToString() : strprintf("%d", id);
return fLogIPs ? addr.ToStringAddrPort() : strprintf("%d", id);
}
Network CNode::ConnectedThroughNetwork() const
@ -772,7 +768,7 @@ void CNode::CopyStats(CNodeStats& stats)
// Leave string empty if addrLocal invalid (not filled in yet)
CService addrLocalUnlocked = GetAddrLocal();
stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToString() : "";
stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToStringAddrPort() : "";
{
LOCK(cs_mnauth);
@ -1421,7 +1417,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
std::string strDropped;
if (fLogIPs) {
strDropped = strprintf("connection from %s dropped", addr.ToString());
strDropped = strprintf("connection from %s dropped", addr.ToStringAddrPort());
} else {
strDropped = "connection dropped";
}
@ -1442,7 +1438,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
const int on{1};
if (sock->SetSockOpt(IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == SOCKET_ERROR) {
LogPrint(BCLog::NET, "connection from %s: unable to set TCP_NODELAY, continuing anyway\n",
addr.ToString());
addr.ToStringAddrPort());
}
// Don't accept connections from banned peers.
@ -1457,7 +1453,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
bool discouraged = m_banman && m_banman->IsDiscouraged(addr);
if (!NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::NoBan) && nInbound + 1 >= nMaxInbound && discouraged)
{
LogPrint(BCLog::NET, "connection from %s dropped (discouraged)\n", addr.ToString());
LogPrint(BCLog::NET, "connection from %s dropped (discouraged)\n", addr.ToStringAddrPort());
return;
}
@ -1510,7 +1506,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
{
LOCK(pnode->m_sock_mutex);
if (fLogIPs) {
LogPrint(BCLog::NET_NETCONN, "connection from %s accepted, sock=%d, peer=%d\n", addr.ToString(), pnode->m_sock->Get(), pnode->GetId());
LogPrint(BCLog::NET_NETCONN, "connection from %s accepted, sock=%d, peer=%d\n", addr.ToStringAddrPort(), pnode->m_sock->Get(), pnode->GetId());
} else {
LogPrint(BCLog::NET_NETCONN, "connection accepted, sock=%d, peer=%d\n", pnode->m_sock->Get(), pnode->GetId());
}
@ -1627,7 +1623,7 @@ void CConnman::DisconnectNodes()
if (fLogIPs) {
LogPrintf("ThreadSocketHandler -- removing node: peer=%d addr=%s nRefCount=%d fInbound=%d m_masternode_connection=%d m_masternode_iqr_connection=%d\n",
pnode->GetId(), pnode->addr.ToString(), pnode->GetRefCount(), pnode->IsInboundConn(), pnode->m_masternode_connection, pnode->m_masternode_iqr_connection);
pnode->GetId(), pnode->addr.ToStringAddrPort(), pnode->GetRefCount(), pnode->IsInboundConn(), pnode->m_masternode_connection, pnode->m_masternode_iqr_connection);
} else {
LogPrintf("ThreadSocketHandler -- removing node: peer=%d nRefCount=%d fInbound=%d m_masternode_connection=%d m_masternode_iqr_connection=%d\n",
pnode->GetId(), pnode->GetRefCount(), pnode->IsInboundConn(), pnode->m_masternode_connection, pnode->m_masternode_iqr_connection);
@ -2404,7 +2400,7 @@ void CConnman::ThreadDNSAddressSeed()
if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) {
// When -forcednsseed is provided, query all.
seeds_right_now = seeds.size();
} else if (addrman.size() == 0) {
} else if (addrman.Size() == 0) {
// If we have no known peers, query all.
// This will occur on the first run, or if peers.dat has been
// deleted.
@ -2423,13 +2419,13 @@ void CConnman::ThreadDNSAddressSeed()
// * If we continue having problems, eventually query all the
// DNS seeds, and if that fails too, also try the fixed seeds.
// (done in ThreadOpenConnections)
const std::chrono::seconds seeds_wait_time = (addrman.size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
const std::chrono::seconds seeds_wait_time = (addrman.Size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
for (const std::string& seed : seeds) {
if (seeds_right_now == 0) {
seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE;
if (addrman.size() > 0) {
if (addrman.Size() > 0) {
LogPrintf("Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
std::chrono::seconds to_wait = seeds_wait_time;
while (to_wait.count() > 0) {
@ -2476,7 +2472,6 @@ void CConnman::ThreadDNSAddressSeed()
if (HaveNameProxy()) {
AddAddrFetch(seed);
} else {
std::vector<CNetAddr> vIPs;
std::vector<CAddress> vAdd;
ServiceFlags requiredServiceBits = GetDesirableServiceFlags(NODE_NONE);
std::string host = strprintf("x%x.%s", requiredServiceBits, seed);
@ -2485,8 +2480,9 @@ void CConnman::ThreadDNSAddressSeed()
continue;
}
unsigned int nMaxIPs = 256; // Limits number of IPs learned from a DNS seed
if (LookupHost(host, vIPs, nMaxIPs, true)) {
for (const CNetAddr& ip : vIPs) {
const auto addresses{LookupHost(host, nMaxIPs, true)};
if (!addresses.empty()) {
for (const CNetAddr& ip : addresses) {
int nOneDay = 24*3600;
CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits);
addr.nTime = GetTime() - 3*nOneDay - rng.randrange(4*nOneDay); // use a random age between 3 and 7 days old
@ -2513,7 +2509,7 @@ void CConnman::DumpAddresses()
DumpPeerAddresses(::gArgs, addrman);
LogPrint(BCLog::NET, "Flushed %d addresses to peers.dat %dms\n",
addrman.size(), GetTimeMillis() - nStart);
addrman.Size(), GetTimeMillis() - nStart);
}
void CConnman::ProcessAddrFetch()
@ -2583,6 +2579,19 @@ int CConnman::GetExtraBlockRelayCount() const
return std::max(block_relay_peers - m_max_outbound_block_relay, 0);
}
std::unordered_set<Network> CConnman::GetReachableEmptyNetworks() const
{
std::unordered_set<Network> networks{};
for (int n = 0; n < NET_MAX; n++) {
enum Network net = (enum Network)n;
if (net == NET_UNROUTABLE || net == NET_INTERNAL) continue;
if (IsReachable(net) && addrman.Size(net, std::nullopt) == 0) {
networks.insert(net);
}
}
return networks;
}
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDeterministicMNManager& dmnman)
{
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
@ -2631,7 +2640,8 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
if (interruptNet)
return;
if (add_fixed_seeds && addrman.size() == 0) {
const std::unordered_set<Network> fixed_seed_networks{GetReachableEmptyNetworks()};
if (add_fixed_seeds && !fixed_seed_networks.empty()) {
// When the node starts with an empty peers.dat, there are a few other sources of peers before
// we fallback on to fixed seeds: -dnsseed, -seednode, -addnode
// If none of those are available, we fallback on to fixed seeds immediately, else we allow
@ -2640,7 +2650,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
// It is cheapest to check if enough time has passed first.
if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
add_fixed_seeds_now = true;
LogPrintf("Adding fixed seeds as 60 seconds have passed and addrman is empty\n");
LogPrintf("Adding fixed seeds as 60 seconds have passed and addrman is empty for at least one reachable network\n");
}
// Checking !dnsseed is cheaper before locking 2 mutexes.
@ -2648,15 +2658,26 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
LOCK2(m_addr_fetches_mutex, m_added_nodes_mutex);
if (m_addr_fetches.empty() && m_added_nodes.empty()) {
add_fixed_seeds_now = true;
LogPrintf("Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n");
LogPrintf("Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet), -addnode is not provided and all -seednode(s) attempted\n");
}
}
if (add_fixed_seeds_now) {
std::vector<CAddress> seed_addrs{ConvertSeeds(Params().FixedSeeds())};
// We will not make outgoing connections to peers that are unreachable
// (e.g. because of -onlynet configuration).
// Therefore, we do not add them to addrman in the first place.
// In case previously unreachable networks become reachable
// (e.g. in case of -onlynet changes by the user), fixed seeds will
// be loaded only for networks for which we have no addressses.
seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(),
[&fixed_seed_networks](const CAddress& addr) { return fixed_seed_networks.count(addr.GetNetwork()) == 0; }),
seed_addrs.end());
CNetAddr local;
local.SetInternal("fixedseeds");
addrman.Add(ConvertSeeds(Params().FixedSeeds()), local);
addrman.Add(seed_addrs, local);
add_fixed_seeds = false;
LogPrintf("Added %d fixed seeds from reachable networks.\n", seed_addrs.size());
}
}
@ -2783,7 +2804,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
!HasAllDesirableServiceFlags(addr.nServices) ||
setConnected.count(m_netgroupman.GetGroup(addr))) continue;
addrConnect = addr;
LogPrint(BCLog::NET, "Trying to make an anchor connection to %s\n", addrConnect.ToString());
LogPrint(BCLog::NET, "Trying to make an anchor connection to %s\n", addrConnect.ToStringAddrPort());
break;
}
@ -2880,7 +2901,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
return;
}
if (fLogIPs) {
LogPrint(BCLog::NET, "Making feeler connection to %s\n", addrConnect.ToString());
LogPrint(BCLog::NET, "Making feeler connection to %s\n", addrConnect.ToStringAddrPort());
} else {
LogPrint(BCLog::NET, "Making feeler connection\n");
}
@ -3049,7 +3070,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman,
if (pnode->nTimeFirstMessageReceived != 0 && GetTimeSeconds() - pnode->nTimeFirstMessageReceived > 5) {
// clearly not expecting mnauth to take that long even if it wasn't the first message
// we received (as it should normally), disconnect
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- dropping non-mnauth connection to %s, service=%s\n", _func_, proRegTxHash.ToString(), addr2.ToString());
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- dropping non-mnauth connection to %s, service=%s\n", _func_, proRegTxHash.ToString(), addr2.ToStringAddrPort());
pnode->fDisconnect = true;
return true;
}
@ -3108,7 +3129,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman,
auto dmn = mnList.GetValidMN(vPendingMasternodes.front());
vPendingMasternodes.erase(vPendingMasternodes.begin());
if (dmn && !connectedNodes.count(dmn->pdmnState->addr) && !IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) {
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- opening pending masternode connection to %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToString());
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- opening pending masternode connection to %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort());
return dmn;
}
}
@ -3117,7 +3138,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman,
// not-null
auto dmn = pending[GetRand(pending.size())];
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- opening quorum connection to %s, service=%s\n",
_func_, dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToString());
_func_, dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort());
return dmn;
}
@ -3127,7 +3148,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman,
masternodePendingProbes.erase(dmn->proTxHash);
isProbe = MasternodeProbeConn::IsConnection;
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- probing masternode %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToString());
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- probing masternode %s, service=%s\n", _func_, dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringAddrPort());
return dmn;
}
return nullptr;
@ -3152,7 +3173,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman,
return true;
});
if (!connected) {
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- connection failed for masternode %s, service=%s\n", __func__, connectToDmn->proTxHash.ToString(), connectToDmn->pdmnState->addr.ToString());
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- connection failed for masternode %s, service=%s\n", __func__, connectToDmn->proTxHash.ToString(), connectToDmn->pdmnState->addr.ToStringAddrPort());
// Will take a few consequent failed attempts to PoSe-punish a MN.
if (mn_metaman.GetMetaInfo(connectToDmn->proTxHash)->OutboundFailedTooManyTimes()) {
LogPrint(BCLog::NET_NETCONN, "CConnman::%s -- failed to connect to masternode %s too many times\n", __func__, connectToDmn->proTxHash.ToString());
@ -3179,7 +3200,7 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
auto getIpStr = [&]() {
if (fLogIPs) {
return addrConnect.ToString();
return addrConnect.ToStringAddrPort();
} else {
return std::string("new peer");
}
@ -3354,7 +3375,7 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
socklen_t len = sizeof(sockaddr);
if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
{
strError = strprintf(Untranslated("Error: Bind address family for %s not supported"), addrBind.ToString());
strError = strprintf(Untranslated("Error: Bind address family for %s not supported"), addrBind.ToStringAddrPort());
LogPrintf("%s\n", strError.original);
return false;
}
@ -3394,13 +3415,13 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
if (sock->Bind(reinterpret_cast<struct sockaddr*>(&sockaddr), len) == SOCKET_ERROR) {
int nErr = WSAGetLastError();
if (nErr == WSAEADDRINUSE)
strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToString(), PACKAGE_NAME);
strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToStringAddrPort(), PACKAGE_NAME);
else
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToStringAddrPort(), NetworkErrorString(nErr));
LogPrintf("%s\n", strError.original);
return false;
}
LogPrintf("Bound to %s\n", addrBind.ToString());
LogPrintf("Bound to %s\n", addrBind.ToStringAddrPort());
// Listen for incoming connections
if (sock->Listen(SOMAXCONN) == SOCKET_ERROR)
@ -3430,14 +3451,11 @@ void Discover()
char pszHostName[256] = "";
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
{
std::vector<CNetAddr> vaddr;
if (LookupHost(pszHostName, vaddr, 0, true))
const std::vector<CNetAddr> addresses{LookupHost(pszHostName, 0, true)};
for (const CNetAddr& addr : addresses)
{
for (const CNetAddr &addr : vaddr)
{
if (AddLocal(addr, LOCAL_IF))
LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToString());
}
if (AddLocal(addr, LOCAL_IF))
LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToStringAddr());
}
}
#elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
@ -3456,14 +3474,14 @@ void Discover()
struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
CNetAddr addr(s4->sin_addr);
if (AddLocal(addr, LOCAL_IF))
LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, addr.ToStringAddr());
}
else if (ifa->ifa_addr->sa_family == AF_INET6)
{
struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
CNetAddr addr(s6->sin6_addr);
if (AddLocal(addr, LOCAL_IF))
LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, addr.ToStringAddr());
}
}
freeifaddrs(myaddrs);
@ -4249,7 +4267,7 @@ CNode::CNode(NodeId idIn,
m_connected{GetTime<std::chrono::seconds>()},
addr{addrIn},
addrBind{addrBindIn},
m_addr_name{addrNameIn.empty() ? addr.ToStringIPPort() : addrNameIn},
m_addr_name{addrNameIn.empty() ? addr.ToStringAddrPort() : addrNameIn},
m_inbound_onion{inbound_onion},
nKeyedNetGroup{nKeyedNetGroupIn},
id{idIn},
@ -4410,7 +4428,7 @@ void CaptureMessageToFile(const CAddress& addr,
auto now = GetTime<std::chrono::microseconds>();
// Windows folder names can not include a colon
std::string clean_addr = addr.ToString();
std::string clean_addr = addr.ToStringAddrPort();
std::replace(clean_addr.begin(), clean_addr.end(), ':', '_');
fs::path base_path = gArgs.GetDataDirNet() / "message_capture" / clean_addr;

View File

@ -45,6 +45,7 @@
#include <optional>
#include <queue>
#include <thread>
#include <unordered_set>
#include <vector>
class CConnman;
@ -1476,6 +1477,12 @@ private:
void RecordBytesRecv(uint64_t bytes);
void RecordBytesSent(uint64_t bytes) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex);
/**
Return reachable networks for which we have no addresses in addrman and therefore
may require loading fixed seeds.
*/
std::unordered_set<Network> GetReachableEmptyNetworks() const;
/**
* Return vector of current BLOCK_RELAY peers.
*/

View File

@ -88,18 +88,18 @@ bool NetWhitebindPermissions::TryParse(const std::string& str, NetWhitebindPermi
if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
const std::string strBind = str.substr(offset);
CService addrBind;
if (!Lookup(strBind, addrBind, 0, false)) {
const std::optional<CService> addrBind{Lookup(strBind, 0, false)};
if (!addrBind.has_value()) {
error = ResolveErrMsg("whitebind", strBind);
return false;
}
if (addrBind.GetPort() == 0) {
if (addrBind.value().GetPort() == 0) {
error = strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind);
return false;
}
output.m_flags = flags;
output.m_service = addrBind;
output.m_service = addrBind.value();
error = Untranslated("");
return true;
}

View File

@ -1374,7 +1374,7 @@ void PeerManagerImpl::PushNodeVersion(CNode& pnode, const Peer& peer)
nonce, strSubVersion, nNodeStartingHeight, tx_relay, mnauthChallenge, pnode.m_masternode_connection.load()));
if (fLogIPs) {
LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, them=%s, txrelay=%d, peer=%d\n", nProtocolVersion, nNodeStartingHeight, addr_you.ToString(), tx_relay, nodeid);
LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, them=%s, txrelay=%d, peer=%d\n", nProtocolVersion, nNodeStartingHeight, addr_you.ToStringAddrPort(), tx_relay, nodeid);
} else {
LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, txrelay=%d, peer=%d\n", nProtocolVersion, nNodeStartingHeight, tx_relay, nodeid);
}
@ -3377,7 +3377,7 @@ void PeerManagerImpl::ProcessMessage(
// Disconnect if we connected to ourself
if (pfrom.IsInboundConn() && !m_connman.CheckIncomingNonce(nNonce))
{
LogPrintf("connected to self at %s, disconnecting\n", pfrom.addr.ToString());
LogPrintf("connected to self at %s, disconnecting\n", pfrom.addr.ToStringAddrPort());
pfrom.fDisconnect = true;
return;
}
@ -3464,7 +3464,7 @@ void PeerManagerImpl::ProcessMessage(
FastRandomContext insecure_rand;
if (addr.IsRoutable())
{
LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToString());
LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToStringAddrPort());
PushAddress(*peer, addr, insecure_rand);
} else if (IsPeerAddrLocalGood(&pfrom)) {
// Override just the address with whatever the peer sees us as.
@ -3472,7 +3472,7 @@ void PeerManagerImpl::ProcessMessage(
// above, as this is an outbound connection and the peer cannot
// observe our listening port.
addr.SetIP(addrMe);
LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToString());
LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToStringAddrPort());
PushAddress(*peer, addr, insecure_rand);
}
}
@ -3505,11 +3505,11 @@ void PeerManagerImpl::ProcessMessage(
std::string remoteAddr;
if (fLogIPs)
remoteAddr = ", peeraddr=" + pfrom.addr.ToString();
remoteAddr = ", peeraddr=" + pfrom.addr.ToStringAddrPort();
LogPrint(BCLog::NET, "receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s\n",
cleanSubVer, pfrom.nVersion,
peer->m_starting_height, addrMe.ToString(), fRelay, pfrom.GetId(),
peer->m_starting_height, addrMe.ToStringAddrPort(), fRelay, pfrom.GetId(),
remoteAddr);
int64_t nTimeOffset = nTime - GetTime();
@ -3544,7 +3544,7 @@ void PeerManagerImpl::ProcessMessage(
if (!pfrom.IsInboundConn()) {
LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n",
pfrom.nVersion.load(), peer->m_starting_height,
pfrom.GetId(), (fLogIPs ? strprintf(", peeraddr=%s", pfrom.addr.ToString()) : ""),
pfrom.GetId(), (fLogIPs ? strprintf(", peeraddr=%s", pfrom.addr.ToStringAddrPort()) : ""),
pfrom.ConnectionTypeAsString());
}

View File

@ -609,7 +609,7 @@ static std::string OnionToString(Span<const uint8_t> addr)
return EncodeBase32(address) + ".onion";
}
std::string CNetAddr::ToStringIP() const
std::string CNetAddr::ToStringAddr() const
{
switch (m_net) {
case NET_IPV4:
@ -633,11 +633,6 @@ std::string CNetAddr::ToStringIP() const
assert(false);
}
std::string CNetAddr::ToString() const
{
return ToStringIP();
}
bool operator==(const CNetAddr& a, const CNetAddr& b)
{
return a.m_net == b.m_net && a.m_addr == b.m_addr;
@ -935,25 +930,17 @@ std::vector<unsigned char> CService::GetKey() const
return key;
}
std::string CService::ToStringPort() const
std::string CService::ToStringAddrPort() const
{
return strprintf("%u", port);
}
const auto port_str = strprintf("%u", port);
std::string CService::ToStringIPPort() const
{
if (IsIPv4() || IsTor() || IsI2P() || IsInternal()) {
return ToStringIP() + ":" + ToStringPort();
return ToStringAddr() + ":" + port_str;
} else {
return "[" + ToStringIP() + "]:" + ToStringPort();
return "[" + ToStringAddr() + "]:" + port_str;
}
}
std::string CService::ToString() const
{
return ToStringIPPort();
}
CSubNet::CSubNet():
valid(false)
{
@ -1117,7 +1104,7 @@ std::string CSubNet::ToString() const
break;
}
return network.ToString() + suffix;
return network.ToStringAddr() + suffix;
}
bool CSubNet::IsValid() const

View File

@ -200,8 +200,7 @@ public:
bool IsAddrV1Compatible() const;
enum Network GetNetwork() const;
std::string ToString() const;
std::string ToStringIP() const;
std::string ToStringAddr() const;
uint64_t GetHash() const;
bool GetInAddr(struct in_addr* pipv4Addr) const;
Network GetNetClass() const;
@ -545,9 +544,7 @@ public:
friend bool operator!=(const CService& a, const CService& b) { return !(a == b); }
friend bool operator<(const CService& a, const CService& b);
std::vector<unsigned char> GetKey() const;
std::string ToString() const;
std::string ToStringPort() const;
std::string ToStringIPPort() const;
std::string ToStringAddrPort() const;
CService(const struct in6_addr& ipv6Addr, uint16_t port);
explicit CService(const struct sockaddr_in6& addr);

View File

@ -131,14 +131,9 @@ std::vector<std::string> GetNetworkNames(bool append_unroutable)
return names;
}
static bool LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
static std::vector<CNetAddr> LookupIntern(const std::string& name, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
vIP.clear();
if (!ValidAsCString(name)) {
return false;
}
if (!ValidAsCString(name)) return {};
{
CNetAddr addr;
// From our perspective, onion addresses are not hostnames but rather
@ -147,83 +142,65 @@ static bool LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, un
// getaddrinfo to decode them and it wouldn't make sense to resolve
// them, we return a network address representing it instead. See
// CNetAddr::SetSpecial(const std::string&) for more details.
if (addr.SetSpecial(name)) {
vIP.push_back(addr);
return true;
}
if (addr.SetSpecial(name)) return {addr};
}
std::vector<CNetAddr> addresses;
for (const CNetAddr& resolved : dns_lookup_function(name, fAllowLookup)) {
if (nMaxSolutions > 0 && vIP.size() >= nMaxSolutions) {
if (nMaxSolutions > 0 && addresses.size() >= nMaxSolutions) {
break;
}
/* Never allow resolving to an internal address. Consider any such result invalid */
if (!resolved.IsInternal()) {
vIP.push_back(resolved);
addresses.push_back(resolved);
}
}
return (vIP.size() > 0);
return addresses;
}
bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
std::vector<CNetAddr> LookupHost(const std::string& name, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
if (!ValidAsCString(name)) {
return false;
}
if (!ValidAsCString(name)) return {};
std::string strHost = name;
if (strHost.empty())
return false;
if (strHost.empty()) return {};
if (strHost.front() == '[' && strHost.back() == ']') {
strHost = strHost.substr(1, strHost.size() - 2);
}
return LookupIntern(strHost, vIP, nMaxSolutions, fAllowLookup, dns_lookup_function);
return LookupIntern(strHost, nMaxSolutions, fAllowLookup, dns_lookup_function);
}
bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSLookupFn dns_lookup_function)
std::optional<CNetAddr> LookupHost(const std::string& name, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
if (!ValidAsCString(name)) {
return false;
}
std::vector<CNetAddr> vIP;
LookupHost(name, vIP, 1, fAllowLookup, dns_lookup_function);
if(vIP.empty())
return false;
addr = vIP.front();
return true;
const std::vector<CNetAddr> addresses{LookupHost(name, 1, fAllowLookup, dns_lookup_function)};
return addresses.empty() ? std::nullopt : std::make_optional(addresses.front());
}
bool Lookup(const std::string& name, std::vector<CService>& vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
std::vector<CService> Lookup(const std::string& name, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
{
if (name.empty() || !ValidAsCString(name)) {
return false;
return {};
}
uint16_t port{portDefault};
std::string hostname;
SplitHostPort(name, port, hostname);
std::vector<CNetAddr> vIP;
bool fRet = LookupIntern(hostname, vIP, nMaxSolutions, fAllowLookup, dns_lookup_function);
if (!fRet)
return false;
vAddr.resize(vIP.size());
for (unsigned int i = 0; i < vIP.size(); i++)
vAddr[i] = CService(vIP[i], port);
return true;
const std::vector<CNetAddr> addresses{LookupIntern(hostname, nMaxSolutions, fAllowLookup, dns_lookup_function)};
if (addresses.empty()) return {};
std::vector<CService> services;
services.reserve(addresses.size());
for (const auto& addr : addresses)
services.emplace_back(addr, port);
return services;
}
bool Lookup(const std::string& name, CService& addr, uint16_t portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function)
std::optional<CService> Lookup(const std::string& name, uint16_t portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function)
{
if (!ValidAsCString(name)) {
return false;
}
std::vector<CService> vService;
bool fRet = Lookup(name, vService, portDefault, fAllowLookup, 1, dns_lookup_function);
if (!fRet)
return false;
addr = vService[0];
return true;
const std::vector<CService> services{Lookup(name, portDefault, fAllowLookup, 1, dns_lookup_function)};
return services.empty() ? std::nullopt : std::make_optional(services.front());
}
CService LookupNumeric(const std::string& name, uint16_t portDefault, DNSLookupFn dns_lookup_function)
@ -231,12 +208,9 @@ CService LookupNumeric(const std::string& name, uint16_t portDefault, DNSLookupF
if (!ValidAsCString(name)) {
return {};
}
CService addr;
// "1.2:345" will fail to resolve the ip, but will still set the port.
// If the ip fails to resolve, re-init the result.
if(!Lookup(name, addr, portDefault, false, dns_lookup_function))
addr = CService();
return addr;
return Lookup(name, portDefault, /*fAllowLookup=*/false, dns_lookup_function).value_or(CService{});
}
/** SOCKS version */
@ -488,7 +462,7 @@ std::unique_ptr<Sock> CreateSockTCP(const CService& address_family)
struct sockaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr);
if (!address_family.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
LogPrintf("Cannot create socket for %s: unsupported network\n", address_family.ToString());
LogPrintf("Cannot create socket for %s: unsupported network\n", address_family.ToStringAddrPort());
return nullptr;
}
@ -549,11 +523,11 @@ bool ConnectSocketDirectly(const CService &addrConnect, const Sock& sock, int nT
struct sockaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr);
if (sock.Get() == INVALID_SOCKET) {
LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToString());
LogPrintf("Cannot connect to %s: invalid socket\n", addrConnect.ToStringAddrPort());
return false;
}
if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToStringAddrPort());
return false;
}
@ -570,11 +544,11 @@ bool ConnectSocketDirectly(const CService &addrConnect, const Sock& sock, int nT
Sock::Event occurred;
if (!sock.Wait(std::chrono::milliseconds{nTimeout}, requested, &occurred)) {
LogPrintf("wait for connect to %s failed: %s\n",
addrConnect.ToString(),
addrConnect.ToStringAddrPort(),
NetworkErrorString(WSAGetLastError()));
return false;
} else if (occurred == 0) {
LogPrint(BCLog::NET, "connection attempt to %s timed out\n", addrConnect.ToString());
LogPrint(BCLog::NET, "connection attempt to %s timed out\n", addrConnect.ToStringAddrPort());
return false;
}
@ -586,13 +560,13 @@ bool ConnectSocketDirectly(const CService &addrConnect, const Sock& sock, int nT
socklen_t sockerr_len = sizeof(sockerr);
if (sock.GetSockOpt(SOL_SOCKET, SO_ERROR, (sockopt_arg_type)&sockerr, &sockerr_len) ==
SOCKET_ERROR) {
LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToStringAddrPort(), NetworkErrorString(WSAGetLastError()));
return false;
}
if (sockerr != 0) {
LogConnectFailure(manual_connection,
"connect() to %s failed after wait: %s",
addrConnect.ToString(),
addrConnect.ToStringAddrPort(),
NetworkErrorString(sockerr));
return false;
}
@ -603,7 +577,7 @@ bool ConnectSocketDirectly(const CService &addrConnect, const Sock& sock, int nT
else
#endif
{
LogConnectFailure(manual_connection, "connect() to %s failed: %s", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
LogConnectFailure(manual_connection, "connect() to %s failed: %s", addrConnect.ToStringAddrPort(), NetworkErrorString(WSAGetLastError()));
return false;
}
}
@ -689,27 +663,27 @@ bool LookupSubNet(const std::string& subnet_str, CSubNet& subnet_out)
const size_t slash_pos{subnet_str.find_last_of('/')};
const std::string str_addr{subnet_str.substr(0, slash_pos)};
CNetAddr addr;
const std::optional<CNetAddr> addr{LookupHost(str_addr, /*fAllowLookup=*/false)};
if (LookupHost(str_addr, addr, /*fAllowLookup=*/false)) {
if (addr.has_value()) {
if (slash_pos != subnet_str.npos) {
const std::string netmask_str{subnet_str.substr(slash_pos + 1)};
uint8_t netmask;
if (ParseUInt8(netmask_str, &netmask)) {
// Valid number; assume CIDR variable-length subnet masking.
subnet_out = CSubNet{addr, netmask};
subnet_out = CSubNet{addr.value(), netmask};
return subnet_out.IsValid();
} else {
// Invalid number; try full netmask syntax. Never allow lookup for netmask.
CNetAddr full_netmask;
if (LookupHost(netmask_str, full_netmask, /*fAllowLookup=*/false)) {
subnet_out = CSubNet{addr, full_netmask};
const std::optional<CNetAddr> full_netmask{LookupHost(netmask_str, /*fAllowLookup=*/false)};
if (full_netmask.has_value()) {
subnet_out = CSubNet{addr.value(), full_netmask.value()};
return subnet_out.IsValid();
}
}
} else {
// Single IP subnet (<ipv4>/32 or <ipv6>/128).
subnet_out = CSubNet{addr};
subnet_out = CSubNet{addr.value()};
return subnet_out.IsValid();
}
}

View File

@ -109,24 +109,25 @@ extern DNSLookupFn g_dns_lookup;
* @param name The string representing a host. Could be a name or a numerical
* IP address (IPv6 addresses in their bracketed form are
* allowed).
* @param[out] vIP The resulting network addresses to which the specified host
* string resolved.
*
* @returns Whether or not the specified host string successfully resolved to
* any resulting network addresses.
* @returns The resulting network addresses to which the specified host
* string resolved.
*
* @see Lookup(const std::string&, std::vector<CService>&, uint16_t, bool, unsigned int, DNSLookupFn)
* @see Lookup(const std::string&, uint16_t, bool, unsigned int, DNSLookupFn)
* for additional parameter descriptions.
*/
bool LookupHost(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
std::vector<CNetAddr> LookupHost(const std::string& name, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
/**
* Resolve a host string to its first corresponding network address.
*
* @see LookupHost(const std::string&, std::vector<CNetAddr>&, uint16_t, bool, DNSLookupFn)
* @returns The resulting network address to which the specified host
* string resolved or std::nullopt if host does not resolve to an address.
*
* @see LookupHost(const std::string&, unsigned int, bool, DNSLookupFn)
* for additional parameter descriptions.
*/
bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
std::optional<CNetAddr> LookupHost(const std::string& name, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
/**
* Resolve a service string to its corresponding service.
@ -136,8 +137,6 @@ bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSL
* disambiguated bracketed form), optionally followed by a uint16_t port
* number. (e.g. example.com:8333 or
* [2001:db8:85a3:8d3:1319:8a2e:370:7348]:420)
* @param[out] vAddr The resulting services to which the specified service string
* resolved.
* @param portDefault The default port for resulting services if not specified
* by the service string.
* @param fAllowLookup Whether or not hostname lookups are permitted. If yes,
@ -145,18 +144,18 @@ bool LookupHost(const std::string& name, CNetAddr& addr, bool fAllowLookup, DNSL
* @param nMaxSolutions The maximum number of results we want, specifying 0
* means "as many solutions as we get."
*
* @returns Whether or not the service string successfully resolved to any
* resulting services.
* @returns The resulting services to which the specified service string
* resolved.
*/
bool Lookup(const std::string& name, std::vector<CService>& vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function = g_dns_lookup);
std::vector<CService> Lookup(const std::string& name, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function = g_dns_lookup);
/**
* Resolve a service string to its first corresponding service.
*
* @see Lookup(const std::string&, std::vector<CService>&, uint16_t, bool, unsigned int, DNSLookupFn)
* @see Lookup(const std::string&, uint16_t, bool, unsigned int, DNSLookupFn)
* for additional parameter descriptions.
*/
bool Lookup(const std::string& name, CService& addr, uint16_t portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
std::optional<CService> Lookup(const std::string& name, uint16_t portDefault, bool fAllowLookup, DNSLookupFn dns_lookup_function = g_dns_lookup);
/**
* Resolve a service string with a numeric IP to its first corresponding
@ -164,7 +163,7 @@ bool Lookup(const std::string& name, CService& addr, uint16_t portDefault, bool
*
* @returns The resulting CService if the resolution was successful, [::]:0 otherwise.
*
* @see Lookup(const std::string&, std::vector<CService>&, uint16_t, bool, unsigned int, DNSLookupFn)
* @see Lookup(const std::string&, uint16_t, bool, unsigned int, DNSLookupFn)
* for additional parameter descriptions.
*/
CService LookupNumeric(const std::string& name, uint16_t portDefault = 0, DNSLookupFn dns_lookup_function = g_dns_lookup);

View File

@ -11,7 +11,7 @@ uint256 NetGroupManager::GetAsmapChecksum() const
{
if (!m_asmap.size()) return {};
return SerializeHash(m_asmap);
return (HashWriter{} << m_asmap).GetHash();
}
std::vector<unsigned char> NetGroupManager::GetGroup(const CNetAddr& address) const

View File

@ -393,7 +393,7 @@ bool ClientModel::getProxyInfo(std::string& ip_port) const
{
Proxy ipv4, ipv6;
if (m_node.getProxy((Network) 1, ipv4) && m_node.getProxy((Network) 2, ipv6)) {
ip_port = ipv4.proxy.ToStringIPPort();
ip_port = ipv4.proxy.ToStringAddrPort();
return true;
}
return false;

View File

@ -224,7 +224,8 @@ void MasternodeList::updateDIP3List()
// Address, Protocol, Status, Active Seconds, Last Seen, Pub Key
auto addr_key = dmn.pdmnState->addr.GetKey();
QByteArray addr_ba(reinterpret_cast<const char*>(addr_key.data()), addr_key.size());
QTableWidgetItem* addressItem = new CMasternodeListWidgetItem<QByteArray>(QString::fromStdString(dmn.pdmnState->addr.ToString()), addr_ba);
QTableWidgetItem* addressItem = new CMasternodeListWidgetItem<QByteArray>(
QString::fromStdString(dmn.pdmnState->addr.ToStringAddrPort()), addr_ba);
QTableWidgetItem* typeItem = new QTableWidgetItem(QString::fromStdString(std::string(GetMnType(dmn.nType).description)));
QTableWidgetItem* statusItem = new QTableWidgetItem(dmn.pdmnState->IsBanned() ? tr("POSE_BANNED") : tr("ENABLED"));
QTableWidgetItem* PoSeScoreItem = new CMasternodeListWidgetItem<int>(QString::number(dmn.pdmnState->nPoSePenalty), dmn.pdmnState->nPoSePenalty);

View File

@ -485,24 +485,20 @@ void OptionsDialog::updateProxyValidationState()
void OptionsDialog::updateDefaultProxyNets()
{
const std::optional<CNetAddr> ui_proxy_netaddr{LookupHost(ui->proxyIp->text().toStdString(), /*fAllowLookup=*/false)};
const CService ui_proxy{ui_proxy_netaddr.value_or(CNetAddr{}), ui->proxyPort->text().toUShort()};
Proxy proxy;
std::string strProxy;
QString strDefaultProxyGUI;
bool has_proxy;
model->node().getProxy(NET_IPV4, proxy);
strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
(strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachIPv4->setChecked(true) : ui->proxyReachIPv4->setChecked(false);
has_proxy = model->node().getProxy(NET_IPV4, proxy);
ui->proxyReachIPv4->setChecked(has_proxy && proxy.proxy == ui_proxy);
model->node().getProxy(NET_IPV6, proxy);
strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
(strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachIPv6->setChecked(true) : ui->proxyReachIPv6->setChecked(false);
has_proxy = model->node().getProxy(NET_IPV6, proxy);
ui->proxyReachIPv6->setChecked(has_proxy && proxy.proxy == ui_proxy);
model->node().getProxy(NET_ONION, proxy);
strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
(strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachTor->setChecked(true) : ui->proxyReachTor->setChecked(false);
has_proxy = model->node().getProxy(NET_ONION, proxy);
ui->proxyReachTor->setChecked(has_proxy && proxy.proxy == ui_proxy);
}
void OptionsDialog::updateCoinJoinVisibility()

View File

@ -722,7 +722,9 @@ static UniValue protx_register_common_wrapper(const JSONRPCRequest& request,
}
if (request.params[paramIdx].get_str() != "") {
if (!Lookup(request.params[paramIdx].get_str().c_str(), ptx.addr, Params().GetDefaultPort(), false)) {
if (auto addr = Lookup(request.params[paramIdx].get_str(), Params().GetDefaultPort(), false); addr.has_value()) {
ptx.addr = addr.value();
} else {
throw std::runtime_error(strprintf("invalid network address %s", request.params[paramIdx].get_str()));
}
}
@ -1030,7 +1032,9 @@ static UniValue protx_update_service_common_wrapper(const JSONRPCRequest& reques
ptx.nType = mnType;
ptx.proTxHash = ParseHashV(request.params[0], "proTxHash");
if (!Lookup(request.params[1].get_str().c_str(), ptx.addr, Params().GetDefaultPort(), false)) {
if (auto addr = Lookup(request.params[1].get_str().c_str(), Params().GetDefaultPort(), false); addr.has_value()) {
ptx.addr = addr.value();
} else {
throw std::runtime_error(strprintf("invalid network address %s", request.params[1].get_str()));
}

View File

@ -43,15 +43,16 @@ static RPCHelpMan masternode_connect()
{
std::string strAddress = request.params[0].get_str();
CService addr;
if (!Lookup(strAddress, addr, 0, false))
std::optional<CService> addr{Lookup(strAddress, 0, false)};
if (!addr.has_value()) {
throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Incorrect masternode address %s", strAddress));
}
const NodeContext& node = EnsureAnyNodeContext(request.context);
CConnman& connman = EnsureConnman(node);
connman.OpenMasternodeConnection(CAddress(addr, NODE_NETWORK));
if (!connman.IsConnected(CAddress(addr, NODE_NETWORK), CConnman::AllNodes))
connman.OpenMasternodeConnection(CAddress(addr.value(), NODE_NETWORK));
if (!connman.IsConnected(CAddress(addr.value(), NODE_NETWORK), CConnman::AllNodes))
throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Couldn't connect to masternode %s", strAddress));
return "successfully connected";
@ -115,7 +116,7 @@ static UniValue GetNextMasternodeForPayment(const CChain& active_chain, CDetermi
UniValue obj(UniValue::VOBJ);
obj.pushKV("height", mnList.GetHeight() + heightShift);
obj.pushKV("IP:port", payee->pdmnState->addr.ToString());
obj.pushKV("IP:port", payee->pdmnState->addr.ToStringAddrPort());
obj.pushKV("proTxHash", payee->proTxHash.ToString());
obj.pushKV("outpoint", payee->collateralOutpoint.ToStringShort());
obj.pushKV("payee", IsValidDestination(payeeDest) ? EncodeDestination(payeeDest) : "UNKNOWN");
@ -219,7 +220,7 @@ static RPCHelpMan masternode_status()
UniValue mnObj(UniValue::VOBJ);
// keep compatibility with legacy status for now (might get deprecated/removed later)
mnObj.pushKV("outpoint", node.mn_activeman->GetOutPoint().ToStringShort());
mnObj.pushKV("service", node.mn_activeman->GetService().ToString());
mnObj.pushKV("service", node.mn_activeman->GetService().ToStringAddrPort());
CDeterministicMNCPtr dmn = node.dmnman->GetListAtChainTip().GetMN(node.mn_activeman->GetProTxHash());
if (dmn) {
mnObj.pushKV("proTxHash", dmn->proTxHash.ToString());
@ -612,7 +613,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite)
}
if (strMode == "addr") {
std::string strAddress = dmn.pdmnState->addr.ToString();
std::string strAddress = dmn.pdmnState->addr.ToStringAddrPort();
if (strFilter !="" && strAddress.find(strFilter) == std::string::npos &&
strOutpoint.find(strFilter) == std::string::npos) return;
obj.pushKV(strOutpoint, strAddress);
@ -624,7 +625,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite)
payeeStr << " " << std::setw(10) <<
dmnToLastPaidTime(dmn) << " " << std::setw(6) <<
dmn.pdmnState->nLastPaidHeight << " " <<
dmn.pdmnState->addr.ToString();
dmn.pdmnState->addr.ToStringAddrPort();
std::string strFull = streamFull.str();
if (strFilter !="" && strFull.find(strFilter) == std::string::npos &&
strOutpoint.find(strFilter) == std::string::npos) return;
@ -635,7 +636,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite)
dmnToStatus(dmn) << " " <<
dmn.pdmnState->nPoSePenalty << " " <<
payeeStr << " " <<
dmn.pdmnState->addr.ToString();
dmn.pdmnState->addr.ToStringAddrPort();
std::string strInfo = streamInfo.str();
if (strFilter !="" && strInfo.find(strFilter) == std::string::npos &&
strOutpoint.find(strFilter) == std::string::npos) return;
@ -643,7 +644,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite)
} else if (strMode == "json" || strMode == "recent" || strMode == "evo") {
std::ostringstream streamInfo;
streamInfo << dmn.proTxHash.ToString() << " " <<
dmn.pdmnState->addr.ToString() << " " <<
dmn.pdmnState->addr.ToStringAddrPort() << " " <<
payeeStr << " " <<
dmnToStatus(dmn) << " " <<
dmn.pdmnState->nPoSePenalty << " " <<
@ -658,7 +659,7 @@ static RPCHelpMan masternodelist_helper(bool is_composite)
strOutpoint.find(strFilter) == std::string::npos) return;
UniValue objMN(UniValue::VOBJ);
objMN.pushKV("proTxHash", dmn.proTxHash.ToString());
objMN.pushKV("address", dmn.pdmnState->addr.ToString());
objMN.pushKV("address", dmn.pdmnState->addr.ToStringAddrPort());
objMN.pushKV("payee", payeeStr);
objMN.pushKV("status", dmnToStatus(dmn));
objMN.pushKV("type", std::string(GetMnType(dmn.nType).description));

View File

@ -189,7 +189,7 @@ static RPCHelpMan getpeerinfo()
obj.pushKV("id", stats.nodeid);
obj.pushKV("addr", stats.m_addr_name);
if (stats.addrBind.IsValid()) {
obj.pushKV("addrbind", stats.addrBind.ToString());
obj.pushKV("addrbind", stats.addrBind.ToStringAddrPort());
}
if (!(stats.addrLocal.empty())) {
obj.pushKV("addrlocal", stats.addrLocal);
@ -509,7 +509,7 @@ static RPCHelpMan getaddednodeinfo()
UniValue addresses(UniValue::VARR);
if (info.fConnected) {
UniValue address(UniValue::VOBJ);
address.pushKV("address", info.resolvedAddress.ToString());
address.pushKV("address", info.resolvedAddress.ToStringAddrPort());
address.pushKV("connected", info.fInbound ? "inbound" : "outbound");
addresses.push_back(address);
}
@ -584,7 +584,7 @@ static UniValue GetNetworksInfo()
obj.pushKV("name", GetNetworkName(network));
obj.pushKV("limited", !IsReachable(network));
obj.pushKV("reachable", IsReachable(network));
obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : std::string());
obj.pushKV("proxy", proxy.IsValid() ? proxy.proxy.ToStringAddrPort() : std::string());
obj.pushKV("proxy_randomize_credentials", proxy.randomize_credentials);
networks.push_back(obj);
}
@ -686,7 +686,7 @@ static RPCHelpMan getnetworkinfo()
for (const std::pair<const CNetAddr, LocalServiceInfo> &item : mapLocalHost)
{
UniValue rec(UniValue::VOBJ);
rec.pushKV("address", item.first.ToString());
rec.pushKV("address", item.first.ToStringAddr());
rec.pushKV("port", item.second.nPort);
rec.pushKV("score", item.second.nScore);
localAddresses.push_back(rec);
@ -736,9 +736,10 @@ static RPCHelpMan setban()
isSubnet = true;
if (!isSubnet) {
CNetAddr resolved;
LookupHost(request.params[0].get_str(), resolved, false);
netAddr = resolved;
const std::optional<CNetAddr> addr{LookupHost(request.params[0].get_str(), false)};
if (addr.has_value()) {
netAddr = addr.value();
}
}
else
LookupSubNet(request.params[0].get_str(), subNet);
@ -953,7 +954,7 @@ static RPCHelpMan getnodeaddresses()
UniValue obj(UniValue::VOBJ);
obj.pushKV("time", (int)addr.nTime);
obj.pushKV("services", (uint64_t)addr.nServices);
obj.pushKV("address", addr.ToStringIP());
obj.pushKV("address", addr.ToStringAddr());
obj.pushKV("port", addr.GetPort());
obj.pushKV("network", GetNetworkName(addr.GetNetClass()));
ret.push_back(obj);
@ -995,11 +996,11 @@ static RPCHelpMan addpeeraddress()
const bool tried{request.params[2].isTrue()};
UniValue obj(UniValue::VOBJ);
CNetAddr net_addr;
std::optional<CNetAddr> net_addr{LookupHost(addr_string, false)};
bool success{false};
if (LookupHost(addr_string, net_addr, false)) {
CAddress address{{net_addr, port}, ServiceFlags{NODE_NETWORK}};
if (net_addr.has_value()) {
CAddress address{{net_addr.value(), port}, ServiceFlags{NODE_NETWORK}};
address.nTime = GetAdjustedTime();
// The source address is set equal to the address. This is equivalent to the peer
// announcing itself.

View File

@ -204,7 +204,7 @@ static UniValue BuildQuorumInfo(const llmq::CQuorumBlockProcessor& quorum_block_
const auto& dmn = quorum->members[i];
UniValue mo(UniValue::VOBJ);
mo.pushKV("proTxHash", dmn->proTxHash.ToString());
mo.pushKV("service", dmn->pdmnState->addr.ToString());
mo.pushKV("service", dmn->pdmnState->addr.ToStringAddrPort());
mo.pushKV("pubKeyOperator", dmn->pdmnState->pubKeyOperator.ToString());
mo.pushKV("valid", quorum->qc->validMembers[i]);
if (quorum->qc->validMembers[i]) {
@ -338,7 +338,7 @@ static RPCHelpMan quorum_dkgstatus()
ecj.pushKV("proTxHash", ec.ToString());
if (foundConnections.count(ec)) {
ecj.pushKV("connected", true);
ecj.pushKV("address", foundConnections[ec].ToString());
ecj.pushKV("address", foundConnections[ec].ToStringAddrPort());
} else {
ecj.pushKV("connected", false);
}

View File

@ -73,17 +73,17 @@ StatsdClient::StatsdClient(const std::string& host, const std::string& nodename,
return;
}
CNetAddr netaddr;
if (!LookupHost(m_host, netaddr, /*fAllowLookup=*/true)) {
LogPrintf("ERROR: Unable to lookup host %s, cannot init StatsdClient\n", m_host);
return;
}
if (!netaddr.IsIPv4()) {
LogPrintf("ERROR: Host %s on unsupported network, cannot init StatsdClient\n", m_host);
return;
}
if (!CService(netaddr, port).GetSockAddr(reinterpret_cast<struct sockaddr*>(&m_server.first), &m_server.second)) {
LogPrintf("ERROR: Cannot get socket address for %s, cannot init StatsdClient\n", m_host);
if (auto netaddr = LookupHost(m_host, /*fAllowLookup=*/true); netaddr.has_value()) {
if (!netaddr->IsIPv4()) {
LogPrintf("ERROR: Host %s on unsupported network, cannot init StatsdClient\n", m_host);
return;
}
if (!CService(*netaddr, port).GetSockAddr(reinterpret_cast<struct sockaddr*>(&m_server.first), &m_server.second)) {
LogPrintf("ERROR: Cannot get socket address for %s, cannot init StatsdClient\n", m_host);
return;
}
} else {
LogPrintf("Unable to lookup host %s, cannot init StatsdClient\n", m_host);
return;
}

View File

@ -31,16 +31,16 @@ static int32_t GetCheckRatio(const NodeContext& node_ctx)
static CNetAddr ResolveIP(const std::string& ip)
{
CNetAddr addr;
BOOST_CHECK_MESSAGE(LookupHost(ip, addr, false), strprintf("failed to resolve: %s", ip));
return addr;
const std::optional<CNetAddr> addr{LookupHost(ip, false)};
BOOST_CHECK_MESSAGE(addr.has_value(), strprintf("failed to resolve: %s", ip));
return addr.value_or(CNetAddr{});
}
static CService ResolveService(const std::string& ip, uint16_t port = 0)
{
CService serv;
BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port));
return serv;
const std::optional<CService> serv{Lookup(ip, port, false)};
BOOST_CHECK_MESSAGE(serv.has_value(), strprintf("failed to resolve: %s:%i", ip, port));
return serv.value_or(CService{});
}
@ -65,22 +65,22 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
CNetAddr source = ResolveIP("252.2.2.2");
// Test: Does Addrman respond correctly when empty.
BOOST_CHECK_EQUAL(addrman->size(), 0U);
BOOST_CHECK_EQUAL(addrman->Size(), 0U);
auto addr_null = addrman->Select().first;
BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0");
BOOST_CHECK_EQUAL(addr_null.ToStringAddrPort(), "[::]:0");
// Test: Does Addrman::Add work as expected.
CService addr1 = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
auto addr_ret1 = addrman->Select().first;
BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
BOOST_CHECK_EQUAL(addr_ret1.ToStringAddrPort(), "250.1.1.1:8333");
// Test: Does IP address deduplication work correctly.
// Expected dup IP should not be added.
CService addr1_dup = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(!addrman->Add({CAddress(addr1_dup, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// Test: New table has one addr and we add a diff addr we should
@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
CService addr2 = ResolveService("250.1.1.2", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
BOOST_CHECK(addrman->size() >= 1);
BOOST_CHECK(addrman->Size() >= 1);
// Test: reset addrman and test AddrMan::Add multiple addresses works as expected
addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
BOOST_CHECK(addrman->Add(vAddr, source));
BOOST_CHECK(addrman->size() >= 1);
BOOST_CHECK(addrman->Size() >= 1);
}
BOOST_AUTO_TEST_CASE(addrman_ports)
@ -108,62 +108,62 @@ BOOST_AUTO_TEST_CASE(addrman_ports)
CNetAddr source = ResolveIP("252.2.2.2");
BOOST_CHECK_EQUAL(addrman->size(), 0U);
BOOST_CHECK_EQUAL(addrman->Size(), 0U);
// Test 7; Addr with same IP but diff port does not replace existing addr.
CService addr1 = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
CService addr1_port = ResolveService("250.1.1.1", 8334);
BOOST_CHECK(addrman->Add({CAddress(addr1_port, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), 2U);
BOOST_CHECK_EQUAL(addrman->Size(), 2U);
auto addr_ret2 = addrman->Select().first;
BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333" || addr_ret2.ToString() == "250.1.1.1:8334");
BOOST_CHECK(addr_ret2.ToStringAddrPort() == "250.1.1.1:8333" || addr_ret2.ToStringAddrPort() == "250.1.1.1:8334");
// Test: Add same IP but diff port to tried table; this converts the entry with
// the specified port to tried, but not the other.
addrman->Good(CAddress(addr1_port, NODE_NONE));
BOOST_CHECK_EQUAL(addrman->size(), 2U);
bool newOnly = true;
auto addr_ret3 = addrman->Select(newOnly).first;
BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
BOOST_CHECK_EQUAL(addrman->Size(), 2U);
bool new_only = true;
auto addr_ret3 = addrman->Select(new_only).first;
BOOST_CHECK_EQUAL(addr_ret3.ToStringAddrPort(), "250.1.1.1:8333");
}
BOOST_AUTO_TEST_CASE(addrman_select)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
BOOST_CHECK(!addrman->Select(false).first.IsValid());
BOOST_CHECK(!addrman->Select(true).first.IsValid());
CNetAddr source = ResolveIP("252.2.2.2");
// Test: Select from new with 1 addr in new.
// Add 1 address to the new table
CService addr1 = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
bool newOnly = true;
auto addr_ret1 = addrman->Select(newOnly).first;
BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
BOOST_CHECK(addrman->Select(/*new_only=*/true).first == addr1);
BOOST_CHECK(addrman->Select(/*new_only=*/false).first == addr1);
// Test: move addr to tried, select from new expected nothing returned.
// Move address to the tried table
BOOST_CHECK(addrman->Good(CAddress(addr1, NODE_NONE)));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
auto addr_ret2 = addrman->Select(newOnly).first;
BOOST_CHECK_EQUAL(addr_ret2.ToString(), "[::]:0");
auto addr_ret3 = addrman->Select().first;
BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
BOOST_CHECK(!addrman->Select(/*new_only=*/true).first.IsValid());
BOOST_CHECK(addrman->Select().first == addr1);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
BOOST_CHECK_EQUAL(addrman->size(), 1U);
// Add three addresses to new table.
// Add one address to the new table
CService addr2 = ResolveService("250.3.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, addr2));
BOOST_CHECK(addrman->Select(/*new_only=*/true).first == addr2);
// Add two more addresses to the new table
CService addr3 = ResolveService("250.3.2.2", 9999);
CService addr4 = ResolveService("250.3.3.3", 9999);
BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
BOOST_CHECK(addrman->Add({CAddress(addr3, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
BOOST_CHECK(addrman->Add({CAddress(addr3, NODE_NONE)}, addr2));
BOOST_CHECK(addrman->Add({CAddress(addr4, NODE_NONE)}, ResolveService("250.4.1.1", 8333)));
// Add three addresses to tried table.
@ -171,17 +171,17 @@ BOOST_AUTO_TEST_CASE(addrman_select)
CService addr6 = ResolveService("250.4.5.5", 7777);
CService addr7 = ResolveService("250.4.6.6", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr5, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
BOOST_CHECK(addrman->Add({CAddress(addr5, NODE_NONE)}, addr3));
BOOST_CHECK(addrman->Good(CAddress(addr5, NODE_NONE)));
BOOST_CHECK(addrman->Add({CAddress(addr6, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
BOOST_CHECK(addrman->Add({CAddress(addr6, NODE_NONE)}, addr3));
BOOST_CHECK(addrman->Good(CAddress(addr6, NODE_NONE)));
BOOST_CHECK(addrman->Add({CAddress(addr7, NODE_NONE)}, ResolveService("250.1.1.3", 8333)));
BOOST_CHECK(addrman->Good(CAddress(addr7, NODE_NONE)));
// Test: 6 addrs + 1 addr from last test = 7.
BOOST_CHECK_EQUAL(addrman->size(), 7U);
// 6 addrs + 1 addr from last test = 7.
BOOST_CHECK_EQUAL(addrman->Size(), 7U);
// Test: Select pulls from new and tried regardless of port number.
// Select pulls from new and tried regardless of port number.
std::set<uint16_t> ports;
for (int i = 0; i < 20; ++i) {
ports.insert(addrman->Select().first.GetPort());
@ -189,6 +189,92 @@ BOOST_AUTO_TEST_CASE(addrman_select)
BOOST_CHECK_EQUAL(ports.size(), 3U);
}
BOOST_AUTO_TEST_CASE(addrman_select_by_network)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
BOOST_CHECK(!addrman->Select(/*new_only=*/true, NET_IPV4).first.IsValid());
BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_IPV4).first.IsValid());
// add ipv4 address to the new table
CNetAddr source = ResolveIP("252.2.2.2");
CService addr1 = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
BOOST_CHECK(addrman->Select(/*new_only=*/true, NET_IPV4).first == addr1);
BOOST_CHECK(addrman->Select(/*new_only=*/false, NET_IPV4).first == addr1);
BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_IPV6).first.IsValid());
BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_ONION).first.IsValid());
BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_I2P).first.IsValid());
BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_CJDNS).first.IsValid());
BOOST_CHECK(!addrman->Select(/*new_only=*/true, NET_CJDNS).first.IsValid());
BOOST_CHECK(addrman->Select(/*new_only=*/false).first == addr1);
// add I2P address to the new table
CAddress i2p_addr;
i2p_addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p");
BOOST_CHECK(addrman->Add({i2p_addr}, source));
BOOST_CHECK(addrman->Select(/*new_only=*/true, NET_I2P).first == i2p_addr);
BOOST_CHECK(addrman->Select(/*new_only=*/false, NET_I2P).first == i2p_addr);
BOOST_CHECK(addrman->Select(/*new_only=*/false, NET_IPV4).first == addr1);
BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_IPV6).first.IsValid());
BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_ONION).first.IsValid());
BOOST_CHECK(!addrman->Select(/*new_only=*/false, NET_CJDNS).first.IsValid());
// bump I2P address to tried table
BOOST_CHECK(addrman->Good(i2p_addr));
BOOST_CHECK(!addrman->Select(/*new_only=*/true, NET_I2P).first.IsValid());
BOOST_CHECK(addrman->Select(/*new_only=*/false, NET_I2P).first == i2p_addr);
// add another I2P address to the new table
CAddress i2p_addr2;
i2p_addr2.SetSpecial("c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p");
BOOST_CHECK(addrman->Add({i2p_addr2}, source));
BOOST_CHECK(addrman->Select(/*new_only=*/true, NET_I2P).first == i2p_addr2);
// ensure that both new and tried table are selected from
bool new_selected{false};
bool tried_selected{false};
int counter = 256;
while (--counter > 0 && (!new_selected || !tried_selected)) {
const CAddress selected{addrman->Select(/*new_only=*/false, NET_I2P).first};
BOOST_REQUIRE(selected == i2p_addr || selected == i2p_addr2);
if (selected == i2p_addr) {
tried_selected = true;
} else {
new_selected = true;
}
}
BOOST_CHECK(new_selected);
BOOST_CHECK(tried_selected);
}
BOOST_AUTO_TEST_CASE(addrman_select_special)
{
// use a non-deterministic addrman to ensure a passing test isn't due to setup
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, /*deterministic=*/false, GetCheckRatio(m_node));
// add ipv4 address to the new table
CNetAddr source = ResolveIP("252.2.2.2");
CService addr1 = ResolveService("250.1.1.3", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
// add I2P address to the tried table
CAddress i2p_addr;
i2p_addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p");
BOOST_CHECK(addrman->Add({i2p_addr}, source));
BOOST_CHECK(addrman->Good(i2p_addr));
// since the only ipv4 address is on the new table, ensure that the new
// table gets selected even if new_only is false. if the table was being
// selected at random, this test will sporadically fail
BOOST_CHECK(addrman->Select(/*new_only=*/false, NET_IPV4).first == addr1);
}
BOOST_AUTO_TEST_CASE(addrman_new_collisions)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
@ -197,25 +283,25 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
uint32_t num_addrs{0};
BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
while (num_addrs < 22) { // Magic number! 250.1.1.1 - 250.1.1.22 do not collide with deterministic key = 1
CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
// Test: No collision in new table yet.
BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
}
// Test: new table collision!
CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
uint32_t collisions{1};
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), num_addrs - collisions);
BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);
CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), num_addrs - collisions);
BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);
}
BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
@ -233,7 +319,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
}
AddressPosition addr_pos = addrman->FindAddressEntry(addr).value();
BOOST_CHECK_EQUAL(addr_pos.multiplicity, 1U);
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// if nTime increases, an addr can occur in up to 8 buckets
// The acceptance probability decreases exponentially with existing multiplicity -
@ -247,7 +333,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
AddressPosition addr_pos_multi = addrman->FindAddressEntry(addr).value();
BOOST_CHECK_EQUAL(addr_pos_multi.multiplicity, 8U);
// multiplicity doesn't affect size
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
}
BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
@ -258,7 +344,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
uint32_t num_addrs{0};
BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
while (num_addrs < 35) { // Magic number! 250.1.1.1 - 250.1.1.35 do not collide in tried with deterministic key = 1
CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
@ -287,7 +373,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
// Test: Sanity check, GetAddr should never return anything if addrman
// is empty.
BOOST_CHECK_EQUAL(addrman->size(), 0U);
BOOST_CHECK_EQUAL(addrman->Size(), 0U);
std::vector<CAddress> vAddr1 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
BOOST_CHECK_EQUAL(vAddr1.size(), 0U);
@ -333,11 +419,11 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
}
std::vector<CAddress> vAddr = addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt);
size_t percent23 = (addrman->size() * 23) / 100;
size_t percent23 = (addrman->Size() * 23) / 100;
BOOST_CHECK_EQUAL(vAddr.size(), percent23);
BOOST_CHECK_EQUAL(vAddr.size(), 461U);
// (Addrman.size() < number of addresses added) due to address collisions.
BOOST_CHECK_EQUAL(addrman->size(), 2006U);
// (addrman.Size() < number of addresses added) due to address collisions.
BOOST_CHECK_EQUAL(addrman->Size(), 2006U);
}
@ -351,8 +437,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket_legacy)
AddrInfo info1 = AddrInfo(addr1, source1);
uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
uint256 nKey1 = (HashWriter{} << 1).GetHash();
uint256 nKey2 = (HashWriter{} << 2).GetHash();
BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN), 40);
@ -401,8 +487,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket_legacy)
AddrInfo info1 = AddrInfo(addr1, source1);
uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
uint256 nKey1 = (HashWriter{} << 1).GetHash();
uint256 nKey2 = (HashWriter{} << 2).GetHash();
// Test: Make sure the buckets are what we expect
BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, EMPTY_NETGROUPMAN), 786);
@ -479,8 +565,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
AddrInfo info1 = AddrInfo(addr1, source1);
uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
uint256 nKey1 = (HashWriter{} << 1).GetHash();
uint256 nKey2 = (HashWriter{} << 2).GetHash();
BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, ngm_asmap), 236);
@ -532,8 +618,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
AddrInfo info1 = AddrInfo(addr1, source1);
uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
uint256 nKey1 = (HashWriter{} << 1).GetHash();
uint256 nKey2 = (HashWriter{} << 2).GetHash();
// Test: Make sure the buckets are what we expect
BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, ngm_asmap), 795);
@ -678,7 +764,7 @@ BOOST_AUTO_TEST_CASE(remove_invalid)
addrman->Add({new1, tried1, new2, tried2}, CNetAddr{});
addrman->Good(tried1);
addrman->Good(tried2);
BOOST_REQUIRE_EQUAL(addrman->size(), 4);
BOOST_REQUIRE_EQUAL(addrman->Size(), 4);
stream << *addrman;
@ -701,17 +787,17 @@ BOOST_AUTO_TEST_CASE(remove_invalid)
addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
stream >> *addrman;
BOOST_CHECK_EQUAL(addrman->size(), 2);
BOOST_CHECK_EQUAL(addrman->Size(), 2);
}
BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
BOOST_CHECK(addrman->size() == 0);
BOOST_CHECK(addrman->Size() == 0);
// Empty addrman should return blank addrman info.
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
// Add twenty two addresses.
CNetAddr source = ResolveIP("252.2.2.2");
@ -721,7 +807,7 @@ BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
// No collisions in tried.
BOOST_CHECK(addrman->Good(addr));
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
}
// Ensure Good handles duplicates well.
@ -733,7 +819,7 @@ BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
BOOST_CHECK(!addrman->Good(addr));
// Verify duplicate address not marked as a collision.
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
}
}
@ -755,13 +841,13 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
CService addr36 = ResolveService("250.1.1.36");
BOOST_CHECK(addrman->Add({CAddress(addr36, NODE_NONE)}, source));
BOOST_CHECK(!addrman->Good(addr36));
BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToString(), "250.1.1.19:0");
BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.19:0");
// 36 should be discarded and 19 not evicted.
// This means we keep 19 in the tried table and
// 36 stays in the new table.
addrman->ResolveCollisions();
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
// Lets create two collisions.
for (unsigned int i = 37; i < 59; i++) {
@ -775,28 +861,28 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
BOOST_CHECK(addrman->Add({CAddress(addr59, NODE_NONE)}, source));
BOOST_CHECK(!addrman->Good(addr59));
BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToString(), "250.1.1.10:0");
BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.10:0");
// Cause a second collision in the new table.
BOOST_CHECK(!addrman->Add({CAddress(addr36, NODE_NONE)}, source));
// 36 still cannot be moved from new to tried due to colliding with 19
BOOST_CHECK(!addrman->Good(addr36));
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() != "[::]:0");
BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() != "[::]:0");
// Resolve all collisions.
addrman->ResolveCollisions();
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
}
BOOST_AUTO_TEST_CASE(addrman_evictionworks)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
BOOST_CHECK(addrman->size() == 0);
BOOST_CHECK(addrman->Size() == 0);
// Empty addrman should return blank addrman info.
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
// Add 35 addresses
CNetAddr source = ResolveIP("252.2.2.2");
@ -814,7 +900,7 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
BOOST_CHECK(!addrman->Good(addr));
auto info = addrman->SelectTriedCollision().first;
BOOST_CHECK_EQUAL(info.ToString(), "250.1.1.19:0");
BOOST_CHECK_EQUAL(info.ToStringAddrPort(), "250.1.1.19:0");
// Ensure test of address fails, so that it is evicted.
// Update entry in tried by setting last good connection in the deep past.
@ -823,7 +909,7 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
// Should swap 36 for 19.
addrman->ResolveCollisions();
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
AddressPosition addr_pos{addrman->FindAddressEntry(CAddress(addr, NODE_NONE)).value()};
BOOST_CHECK(addr_pos.tried);
@ -832,18 +918,18 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
// We check this by verifying Good() returns false and also verifying that
// we have no collisions.
BOOST_CHECK(!addrman->Good(addr));
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
// 19 should fail as a collision (not a duplicate) if we now attempt to move
// it to the tried table.
CService addr19 = ResolveService("250.1.1.19");
BOOST_CHECK(!addrman->Good(addr19));
BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToString(), "250.1.1.36:0");
BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.36:0");
// Eviction is also successful if too much time has passed since last try
SetMockTime(GetTime() + 4 * 60 *60);
addrman->ResolveCollisions();
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
//Now 19 is in tried again, and 36 back to new
AddressPosition addr_pos19{addrman->FindAddressEntry(CAddress(addr19, NODE_NONE)).value()};
BOOST_CHECK(addr_pos19.tried);
@ -863,26 +949,31 @@ BOOST_AUTO_TEST_CASE(load_addrman)
{
AddrMan addrman{EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node)};
CService addr1, addr2, addr3;
BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false));
BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false));
BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false));
BOOST_CHECK(Lookup("250.7.3.3"s, addr3, 9999, false));
BOOST_CHECK(!Lookup("250.7.3.3\0example.com"s, addr3, 9999, false));
std::optional<CService> addr1, addr2, addr3, addr4;
addr1 = Lookup("250.7.1.1", 8333, false);
BOOST_CHECK(addr1.has_value());
addr2 = Lookup("250.7.2.2", 9999, false);
BOOST_CHECK(addr2.has_value());
addr3 = Lookup("250.7.3.3", 9999, false);
BOOST_CHECK(addr3.has_value());
addr3 = Lookup("250.7.3.3"s, 9999, false);
BOOST_CHECK(addr3.has_value());
addr4 = Lookup("250.7.3.3\0example.com"s, 9999, false);
BOOST_CHECK(!addr4.has_value());
// Add three addresses to new table.
CService source;
BOOST_CHECK(Lookup("252.5.1.1", source, 8333, false));
std::vector<CAddress> addresses{CAddress(addr1, NODE_NONE), CAddress(addr2, NODE_NONE), CAddress(addr3, NODE_NONE)};
BOOST_CHECK(addrman.Add(addresses, source));
BOOST_CHECK(addrman.size() == 3);
const std::optional<CService> source{Lookup("252.5.1.1", 8333, false)};
BOOST_CHECK(source.has_value());
std::vector<CAddress> addresses{CAddress(addr1.value(), NODE_NONE), CAddress(addr2.value(), NODE_NONE), CAddress(addr3.value(), NODE_NONE)};
BOOST_CHECK(addrman.Add(addresses, source.value()));
BOOST_CHECK(addrman.Size() == 3);
// Test that the de-serialization does not throw an exception.
CDataStream ssPeers1 = AddrmanToStream(addrman);
bool exceptionThrown = false;
AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
BOOST_CHECK(addrman1.size() == 0);
BOOST_CHECK(addrman1.Size() == 0);
try {
unsigned char pchMsgTmp[4];
ssPeers1 >> pchMsgTmp;
@ -891,16 +982,16 @@ BOOST_AUTO_TEST_CASE(load_addrman)
exceptionThrown = true;
}
BOOST_CHECK(addrman1.size() == 3);
BOOST_CHECK(addrman1.Size() == 3);
BOOST_CHECK(exceptionThrown == false);
// Test that ReadFromStream creates an addrman with the correct number of addrs.
CDataStream ssPeers2 = AddrmanToStream(addrman);
AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
BOOST_CHECK(addrman2.size() == 0);
BOOST_CHECK(addrman2.Size() == 0);
ReadFromStream(addrman2, ssPeers2);
BOOST_CHECK(addrman2.size() == 3);
BOOST_CHECK(addrman2.Size() == 3);
}
// Produce a corrupt peers.dat that claims 20 addrs when it only has one addr.
@ -919,12 +1010,12 @@ static CDataStream MakeCorruptPeersDat()
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
s << nUBuckets;
CService serv;
BOOST_CHECK(Lookup("252.1.1.1", serv, 7777, false));
CAddress addr = CAddress(serv, NODE_NONE);
CNetAddr resolved;
BOOST_CHECK(LookupHost("252.2.2.2", resolved, false));
AddrInfo info = AddrInfo(addr, resolved);
const std::optional<CService> serv{Lookup("252.1.1.1", 7777, false)};
BOOST_REQUIRE(serv.has_value());
CAddress addr = CAddress(serv.value(), NODE_NONE);
std::optional<CNetAddr> resolved{LookupHost("252.2.2.2", false)};
BOOST_REQUIRE(resolved.has_value());
AddrInfo info = AddrInfo(addr, resolved.value());
s << info;
return s;
@ -936,7 +1027,7 @@ BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
CDataStream ssPeers1 = MakeCorruptPeersDat();
bool exceptionThrown = false;
AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
BOOST_CHECK(addrman1.size() == 0);
BOOST_CHECK(addrman1.Size() == 0);
try {
unsigned char pchMsgTmp[4];
ssPeers1 >> pchMsgTmp;
@ -945,14 +1036,14 @@ BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
exceptionThrown = true;
}
// Even though de-serialization failed addrman is not left in a clean state.
BOOST_CHECK(addrman1.size() == 1);
BOOST_CHECK(addrman1.Size() == 1);
BOOST_CHECK(exceptionThrown);
// Test that ReadFromStream fails if peers.dat is corrupt
CDataStream ssPeers2 = MakeCorruptPeersDat();
AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
BOOST_CHECK(addrman2.size() == 0);
BOOST_CHECK(addrman2.Size() == 0);
BOOST_CHECK_THROW(ReadFromStream(addrman2, ssPeers2), std::ios_base::failure);
}
@ -966,7 +1057,7 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
int64_t start_time{GetAdjustedTime() - 10000};
addr.nTime = start_time;
BOOST_CHECK(addrman->Add({addr}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// Updating an addrman entry with a different port doesn't change it
CAddress addr_diff_port{CAddress(ResolveService("250.1.1.1", 8334), NODE_NONE)};
@ -987,4 +1078,42 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
BOOST_CHECK_EQUAL(vAddr2.at(0).nServices, NODE_NETWORK_LIMITED);
}
BOOST_AUTO_TEST_CASE(addrman_size)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
const CNetAddr source = ResolveIP("252.2.2.2");
// empty addrman
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 0U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 0U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 0U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 0U);
// add two ipv4 addresses, one to tried and new
const CAddress addr1{ResolveService("250.1.1.1", 8333), NODE_NONE};
BOOST_CHECK(addrman->Add({addr1}, source));
BOOST_CHECK(addrman->Good(addr1));
const CAddress addr2{ResolveService("250.1.1.2", 8333), NODE_NONE};
BOOST_CHECK(addrman->Add({addr2}, source));
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 2U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 1U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/true), 1U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 1U);
// add one i2p address to new
CService i2p_addr;
i2p_addr.SetSpecial("UDHDrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.I2P");
const CAddress addr3{i2p_addr, NODE_NONE};
BOOST_CHECK(addrman->Add({addr3}, source));
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 3U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/std::nullopt), 1U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/true), 1U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 2U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -23,7 +23,11 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots)
smle.confirmedHash.SetHex(strprintf("%064x", i));
std::string ip = strprintf("%d.%d.%d.%d", 0, 0, 0, i);
Lookup(ip.c_str(), smle.service, i, false);
if (auto service = Lookup(ip, i, false); service.has_value()) {
smle.service = service.value();
} else {
BOOST_ASSERT(false);
}
std::vector<unsigned char> vecBytes{static_cast<unsigned char>(i)};
vecBytes.resize(CBLSSecretKey::SerSize);

View File

@ -116,7 +116,7 @@ void FillAddrman(AddrMan& addrman, FuzzedDataProvider& fuzzed_data_provider)
const auto time_penalty = fast_random_context.randrange(100000001);
addrman.Add({addr}, source, time_penalty);
if (n > 0 && addrman.size() % n == 0) {
if (n > 0 && addrman.Size() % n == 0) {
addrman.Good(addr, GetTime());
}
@ -306,7 +306,7 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman)
}
});
}
(void)addr_man.size();
(void)addr_man.Size();
CDataStream data_stream(SER_NETWORK, PROTOCOL_VERSION);
data_stream << addr_man;
}

View File

@ -74,7 +74,7 @@ FUZZ_TARGET(http_request)
const std::string body = http_request.ReadBody();
assert(body.empty());
const CService service = http_request.GetPeer();
assert(service.ToString() == "[::]:0");
assert(service.ToStringAddrPort() == "[::]:0");
evbuffer_free(evbuf);
evhttp_request_free(evreq);

View File

@ -71,8 +71,7 @@ FUZZ_TARGET(netaddress)
assert(net_addr.GetNetwork() == Network::NET_ONION);
}
(void)net_addr.IsValid();
(void)net_addr.ToString();
(void)net_addr.ToStringIP();
(void)net_addr.ToStringAddr();
const CSubNet sub_net{net_addr, fuzzed_data_provider.ConsumeIntegral<uint8_t>()};
(void)sub_net.IsValid();
@ -81,9 +80,7 @@ FUZZ_TARGET(netaddress)
const CService service{net_addr, fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
(void)service.GetKey();
(void)service.GetPort();
(void)service.ToString();
(void)service.ToStringIPPort();
(void)service.ToStringPort();
(void)service.ToStringAddrPort();
const CNetAddr other_net_addr = ConsumeNetAddr(fuzzed_data_provider);
(void)net_addr.GetReachabilityFrom(&other_net_addr);

View File

@ -29,33 +29,29 @@ FUZZ_TARGET(netbase_dns_lookup)
};
{
std::vector<CNetAddr> resolved_addresses;
if (LookupHost(name, resolved_addresses, max_results, allow_lookup, fuzzed_dns_lookup_function)) {
for (const CNetAddr& resolved_address : resolved_addresses) {
assert(!resolved_address.IsInternal());
}
const std::vector<CNetAddr> resolved_addresses{LookupHost(name, max_results, allow_lookup, fuzzed_dns_lookup_function)};
for (const CNetAddr& resolved_address : resolved_addresses) {
assert(!resolved_address.IsInternal());
}
assert(resolved_addresses.size() <= max_results || max_results == 0);
}
{
CNetAddr resolved_address;
if (LookupHost(name, resolved_address, allow_lookup, fuzzed_dns_lookup_function)) {
assert(!resolved_address.IsInternal());
const std::optional<CNetAddr> resolved_address{LookupHost(name, allow_lookup, fuzzed_dns_lookup_function)};
if (resolved_address.has_value()) {
assert(!resolved_address.value().IsInternal());
}
}
{
std::vector<CService> resolved_services;
if (Lookup(name, resolved_services, default_port, allow_lookup, max_results, fuzzed_dns_lookup_function)) {
for (const CNetAddr& resolved_service : resolved_services) {
assert(!resolved_service.IsInternal());
}
const std::vector<CService> resolved_services{Lookup(name, default_port, allow_lookup, max_results, fuzzed_dns_lookup_function)};
for (const CNetAddr& resolved_service : resolved_services) {
assert(!resolved_service.IsInternal());
}
assert(resolved_services.size() <= max_results || max_results == 0);
}
{
CService resolved_service;
if (Lookup(name, resolved_service, default_port, allow_lookup, fuzzed_dns_lookup_function)) {
assert(!resolved_service.IsInternal());
const std::optional<CService> resolved_service{Lookup(name, default_port, allow_lookup, fuzzed_dns_lookup_function)};
if (resolved_service.has_value()) {
assert(!resolved_service.value().IsInternal());
}
}
{

View File

@ -136,49 +136,49 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
CNetAddr addr;
// IPv4, INADDR_ANY
BOOST_REQUIRE(LookupHost("0.0.0.0", addr, false));
addr = LookupHost("0.0.0.0", false).value();
BOOST_REQUIRE(!addr.IsValid());
BOOST_REQUIRE(addr.IsIPv4());
BOOST_CHECK(addr.IsBindAny());
BOOST_CHECK(addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), "0.0.0.0");
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "0.0.0.0");
// IPv4, INADDR_NONE
BOOST_REQUIRE(LookupHost("255.255.255.255", addr, false));
addr = LookupHost("255.255.255.255", false).value();
BOOST_REQUIRE(!addr.IsValid());
BOOST_REQUIRE(addr.IsIPv4());
BOOST_CHECK(!addr.IsBindAny());
BOOST_CHECK(addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), "255.255.255.255");
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "255.255.255.255");
// IPv4, casual
BOOST_REQUIRE(LookupHost("12.34.56.78", addr, false));
addr = LookupHost("12.34.56.78", false).value();
BOOST_REQUIRE(addr.IsValid());
BOOST_REQUIRE(addr.IsIPv4());
BOOST_CHECK(!addr.IsBindAny());
BOOST_CHECK(addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), "12.34.56.78");
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "12.34.56.78");
// IPv6, in6addr_any
BOOST_REQUIRE(LookupHost("::", addr, false));
addr = LookupHost("::", false).value();
BOOST_REQUIRE(!addr.IsValid());
BOOST_REQUIRE(addr.IsIPv6());
BOOST_CHECK(addr.IsBindAny());
BOOST_CHECK(addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), "::");
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "::");
// IPv6, casual
BOOST_REQUIRE(LookupHost("1122:3344:5566:7788:9900:aabb:ccdd:eeff", addr, false));
addr = LookupHost("1122:3344:5566:7788:9900:aabb:ccdd:eeff", false).value();
BOOST_REQUIRE(addr.IsValid());
BOOST_REQUIRE(addr.IsIPv6());
BOOST_CHECK(!addr.IsBindAny());
BOOST_CHECK(addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), "1122:3344:5566:7788:9900:aabb:ccdd:eeff");
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "1122:3344:5566:7788:9900:aabb:ccdd:eeff");
// IPv6, scoped/link-local. See https://tools.ietf.org/html/rfc4007
// We support non-negative decimal integers (uint32_t) as zone id indices.
@ -187,18 +187,18 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
// id of "32", return the address as "fe80::1%32".
const std::string link_local{"fe80::1"};
const std::string scoped_addr{link_local + "%32"};
BOOST_REQUIRE(LookupHost(scoped_addr, addr, false));
addr = LookupHost(scoped_addr, false).value();
BOOST_REQUIRE(addr.IsValid());
BOOST_REQUIRE(addr.IsIPv6());
BOOST_CHECK(!addr.IsBindAny());
BOOST_CHECK_EQUAL(addr.ToString(), scoped_addr);
BOOST_CHECK_EQUAL(addr.ToStringAddr(), scoped_addr);
// Test that the delimiter "%" and default zone id of 0 can be omitted for the default scope.
BOOST_REQUIRE(LookupHost(link_local + "%0", addr, false));
addr = LookupHost(link_local + "%0", false).value();
BOOST_REQUIRE(addr.IsValid());
BOOST_REQUIRE(addr.IsIPv6());
BOOST_CHECK(!addr.IsBindAny());
BOOST_CHECK_EQUAL(addr.ToString(), link_local);
BOOST_CHECK_EQUAL(addr.ToStringAddr(), link_local);
// TORv2, no longer supported
BOOST_CHECK(!addr.SetSpecial("6hzph5hv6337r6p2.onion"));
@ -212,7 +212,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
BOOST_CHECK(!addr.IsI2P());
BOOST_CHECK(!addr.IsBindAny());
BOOST_CHECK(!addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), torv3_addr);
BOOST_CHECK_EQUAL(addr.ToStringAddr(), torv3_addr);
// TORv3, broken, with wrong checksum
BOOST_CHECK(!addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscsad.onion"));
@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
BOOST_CHECK(!addr.IsTor());
BOOST_CHECK(!addr.IsBindAny());
BOOST_CHECK(!addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), ToLower(i2p_addr));
BOOST_CHECK_EQUAL(addr.ToStringAddr(), ToLower(i2p_addr));
// I2P, correct length, but decodes to less than the expected number of bytes.
BOOST_CHECK(!addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jn=.b32.i2p"));
@ -266,7 +266,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_basic)
BOOST_CHECK(!addr.IsBindAny());
BOOST_CHECK(addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), "esffpvrt3wpeaygy.internal");
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "esffpvrt3wpeaygy.internal");
// Totally bogus
BOOST_CHECK(!addr.SetSpecial("totally bogus"));
@ -319,10 +319,9 @@ BOOST_AUTO_TEST_CASE(cnetaddr_tostring_canonical_ipv6)
{"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AaAa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
};
for (const auto& [input_address, expected_canonical_representation_output] : canonical_representations_ipv6) {
CNetAddr net_addr;
BOOST_REQUIRE(LookupHost(input_address, net_addr, false));
BOOST_REQUIRE(net_addr.IsIPv6());
BOOST_CHECK_EQUAL(net_addr.ToString(), expected_canonical_representation_output);
const std::optional<CNetAddr> net_addr{LookupHost(input_address, false)};
BOOST_REQUIRE(net_addr.value().IsIPv6());
BOOST_CHECK_EQUAL(net_addr.value().ToStringAddr(), expected_canonical_representation_output);
}
}
@ -335,12 +334,12 @@ BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v1)
BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000000000000000");
s.clear();
BOOST_REQUIRE(LookupHost("1.2.3.4", addr, false));
addr = LookupHost("1.2.3.4", false).value();
s << addr;
BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000ffff01020304");
s.clear();
BOOST_REQUIRE(LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", addr, false));
addr = LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", false).value();
s << addr;
BOOST_CHECK_EQUAL(HexStr(s), "1a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b");
s.clear();
@ -371,12 +370,12 @@ BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v2)
BOOST_CHECK_EQUAL(HexStr(s), "021000000000000000000000000000000000");
s.clear();
BOOST_REQUIRE(LookupHost("1.2.3.4", addr, false));
addr = LookupHost("1.2.3.4", false).value();
s << addr;
BOOST_CHECK_EQUAL(HexStr(s), "010401020304");
s.clear();
BOOST_REQUIRE(LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", addr, false));
addr = LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", false).value();
s << addr;
BOOST_CHECK_EQUAL(HexStr(s), "02101a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b");
s.clear();
@ -411,7 +410,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_CHECK(addr.IsValid());
BOOST_CHECK(addr.IsIPv4());
BOOST_CHECK(addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), "1.2.3.4");
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "1.2.3.4");
BOOST_REQUIRE(s.empty());
// Invalid IPv4, valid length but address itself is shorter.
@ -448,7 +447,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_CHECK(addr.IsValid());
BOOST_CHECK(addr.IsIPv6());
BOOST_CHECK(addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), "102:304:506:708:90a:b0c:d0e:f10");
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "102:304:506:708:90a:b0c:d0e:f10");
BOOST_REQUIRE(s.empty());
// Valid IPv6, contains embedded "internal".
@ -460,7 +459,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
s >> addr;
BOOST_CHECK(addr.IsInternal());
BOOST_CHECK(addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), "zklycewkdo64v6wc.internal");
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "zklycewkdo64v6wc.internal");
BOOST_REQUIRE(s.empty());
// Invalid IPv6, with bogus length.
@ -506,7 +505,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_CHECK(addr.IsValid());
BOOST_CHECK(addr.IsTor());
BOOST_CHECK(!addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(),
BOOST_CHECK_EQUAL(addr.ToStringAddr(),
"pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion");
BOOST_REQUIRE(s.empty());
@ -529,7 +528,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_CHECK(addr.IsValid());
BOOST_CHECK(addr.IsI2P());
BOOST_CHECK(!addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(),
BOOST_CHECK_EQUAL(addr.ToStringAddr(),
"ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p");
BOOST_REQUIRE(s.empty());
@ -552,7 +551,7 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_CHECK(addr.IsValid());
BOOST_CHECK(addr.IsCJDNS());
BOOST_CHECK(!addr.IsAddrV1Compatible());
BOOST_CHECK_EQUAL(addr.ToString(), "fc00:1:2:3:4:5:6:7");
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "fc00:1:2:3:4:5:6:7");
BOOST_REQUIRE(s.empty());
// Invalid CJDNS, wrong prefix.

View File

@ -25,9 +25,7 @@ BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup)
static CNetAddr ResolveIP(const std::string& ip)
{
CNetAddr addr;
LookupHost(ip, addr, false);
return addr;
return LookupHost(ip, false).value_or(CNetAddr{});
}
static CSubNet ResolveSubNet(const std::string& subnet)
@ -115,7 +113,7 @@ BOOST_AUTO_TEST_CASE(netbase_splithost)
bool static TestParse(std::string src, std::string canon)
{
CService addr(LookupNumeric(src, 65535));
return canon == addr.ToString();
return canon == addr.ToStringAddrPort();
}
BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
@ -139,7 +137,7 @@ BOOST_AUTO_TEST_CASE(embedded_test)
CNetAddr addr1(ResolveIP("1.2.3.4"));
CNetAddr addr2(ResolveIP("::FFFF:0102:0304"));
BOOST_CHECK(addr2.IsIPv4());
BOOST_CHECK_EQUAL(addr1.ToString(), addr2.ToString());
BOOST_CHECK_EQUAL(addr1.ToStringAddr(), addr2.ToStringAddr());
}
BOOST_AUTO_TEST_CASE(subnet_test)
@ -224,7 +222,7 @@ BOOST_AUTO_TEST_CASE(subnet_test)
subnet = CSubNet(tor_addr);
BOOST_CHECK(subnet.IsValid());
BOOST_CHECK_EQUAL(subnet.ToString(), tor_addr.ToString());
BOOST_CHECK_EQUAL(subnet.ToString(), tor_addr.ToStringAddr());
BOOST_CHECK(subnet.Match(tor_addr));
BOOST_CHECK(
!subnet.Match(ResolveIP("kpgvmscirrdqpekbqjsvw5teanhatztpp2gl6eee4zkowvwfxwenqaid.onion")));
@ -562,11 +560,10 @@ BOOST_AUTO_TEST_CASE(netpermissions_test)
BOOST_AUTO_TEST_CASE(netbase_dont_resolve_strings_with_embedded_nul_characters)
{
CNetAddr addr;
BOOST_CHECK(LookupHost("127.0.0.1"s, addr, false));
BOOST_CHECK(!LookupHost("127.0.0.1\0"s, addr, false));
BOOST_CHECK(!LookupHost("127.0.0.1\0example.com"s, addr, false));
BOOST_CHECK(!LookupHost("127.0.0.1\0example.com\0"s, addr, false));
BOOST_CHECK(LookupHost("127.0.0.1"s, false).has_value());
BOOST_CHECK(!LookupHost("127.0.0.1\0"s, false).has_value());
BOOST_CHECK(!LookupHost("127.0.0.1\0example.com"s, false).has_value());
BOOST_CHECK(!LookupHost("127.0.0.1\0example.com\0"s, false).has_value());
CSubNet ret;
BOOST_CHECK(LookupSubNet("1.2.3.0/24"s, ret));
BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0"s, ret));

View File

@ -133,15 +133,15 @@ bool TorControlConnection::Connect(const std::string& tor_control_center, const
Disconnect();
}
CService control_service;
if (!Lookup(tor_control_center, control_service, 9051, fNameLookup)) {
const std::optional<CService> control_service{Lookup(tor_control_center, 9051, fNameLookup)};
if (!control_service.has_value()) {
LogPrintf("tor: Failed to look up control center %s\n", tor_control_center);
return false;
}
struct sockaddr_storage control_address;
socklen_t control_address_len = sizeof(control_address);
if (!control_service.GetSockAddr(reinterpret_cast<struct sockaddr*>(&control_address), &control_address_len)) {
if (!control_service.value().GetSockAddr(reinterpret_cast<struct sockaddr*>(&control_address), &control_address_len)) {
LogPrintf("tor: Error parsing socket address %s\n", tor_control_center);
return false;
}
@ -350,7 +350,7 @@ void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlRe
return;
}
service = LookupNumeric(std::string(service_id+".onion"), Params().GetDefaultPort());
LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString());
LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToStringAddrPort());
if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) {
LogPrint(BCLog::TOR, "tor: Cached service private key to %s\n", fs::PathToString(GetPrivateKeyFile()));
} else {
@ -400,7 +400,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
}
// Request onion service, redirect port.
// Note that the 'virtual' port is always the default port to avoid decloaking nodes using other ports.
_conn.Command(strprintf("ADD_ONION %s Port=%i,%s", private_key, Params().GetDefaultPort(), m_target.ToStringIPPort()),
_conn.Command(strprintf("ADD_ONION %s Port=%i,%s", private_key, Params().GetDefaultPort(), m_target.ToStringAddrPort()),
std::bind(&TorController::add_onion_cb, this, std::placeholders::_1, std::placeholders::_2));
} else {
LogPrintf("tor: Authentication failed\n");

View File

@ -100,9 +100,8 @@ static bool IsZMQAddressIPV6(const std::string &zmq_address)
const size_t colon_index = zmq_address.rfind(":");
if (tcp_index == 0 && colon_index != std::string::npos) {
const std::string ip = zmq_address.substr(tcp_prefix.length(), colon_index - tcp_prefix.length());
CNetAddr addr;
LookupHost(ip, addr, false);
if (addr.IsIPv6()) return true;
const std::optional<CNetAddr> addr{LookupHost(ip, false)};
if (addr.has_value() && addr.value().IsIPv6()) return true;
}
return false;
}

View File

@ -31,12 +31,12 @@ def serialize_addrman(
r += struct.pack("B", format)
r += struct.pack("B", INCOMPATIBILITY_BASE + lowest_compatible)
r += ser_uint256(bucket_key)
r += struct.pack("i", len_new or len(new))
r += struct.pack("i", len_tried or len(tried))
r += struct.pack("<i", len_new or len(new))
r += struct.pack("<i", len_tried or len(tried))
ADDRMAN_NEW_BUCKET_COUNT = 1 << 10
r += struct.pack("i", ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30))
r += struct.pack("<i", ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30))
for _ in range(ADDRMAN_NEW_BUCKET_COUNT):
r += struct.pack("i", 0)
r += struct.pack("<i", 0)
checksum = hash256(r)
r += mock_checksum or checksum
return r

View File

@ -181,11 +181,12 @@ class ConfArgsTest(BitcoinTestFramework):
with self.nodes[0].assert_debug_log(expected_msgs=[
"Loaded 0 addresses from peers.dat",
"DNS seeding disabled",
"Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n",
"Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet), -addnode is not provided and all -seednode(s) attempted\n",
]):
self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1'])
assert time.time() - start < 60
self.stop_node(0)
self.nodes[0].assert_start_raises_init_error(['-dnsseed=1', '-onlynet=i2p', '-i2psam=127.0.0.1:7656'], "Error: Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")
# No peers.dat exists and dns seeds are disabled.
# We expect the node will not add fixed seeds when explicitly disabled.