Skip to content

Commit

Permalink
merge bitcoin#24697: refactor address relay time
Browse files Browse the repository at this point in the history
  • Loading branch information
kwvg committed Dec 8, 2024
1 parent 730cdf2 commit bc3ec30
Show file tree
Hide file tree
Showing 17 changed files with 207 additions and 166 deletions.
147 changes: 77 additions & 70 deletions src/addrman.cpp

Large diffs are not rendered by default.

25 changes: 13 additions & 12 deletions src/addrman.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <protocol.h>
#include <streams.h>
#include <timedata.h>
#include <util/time.h>

#include <cstdint>
#include <memory>
Expand Down Expand Up @@ -124,23 +125,23 @@ class AddrMan
*
* @param[in] vAddr Address records to attempt to add.
* @param[in] source The address of the node that sent us these addr records.
* @param[in] nTimePenalty A "time penalty" to apply to the address record's nTime. If a peer
* @param[in] time_penalty A "time penalty" to apply to the address record's nTime. If a peer
* sends us an address record with nTime=n, then we'll add it to our
* addrman with nTime=(n - nTimePenalty).
* addrman with nTime=(n - time_penalty).
* @return true if at least one address is successfully added. */
bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty = 0);
bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty = 0s);

/**
* Mark an address record as accessible and attempt to move it to addrman's tried table.
*
* @param[in] addr Address record to attempt to move to tried table.
* @param[in] nTime The time that we were last connected to this peer.
* @param[in] time The time that we were last connected to this peer.
* @return true if the address is successfully moved from the new table to the tried table.
*/
bool Good(const CService& addr, int64_t nTime = GetAdjustedTime());
bool Good(const CService& addr, NodeSeconds time = AdjustedTime());

//! Mark an entry as connection attempted to.
void Attempt(const CService& addr, bool fCountFailure, int64_t nTime = GetAdjustedTime());
void Attempt(const CService& addr, bool fCountFailure, NodeSeconds time = AdjustedTime());

//! See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
void ResolveCollisions();
Expand All @@ -150,9 +151,9 @@ class AddrMan
* attempting to evict.
*
* @return CAddress The record for the selected tried peer.
* int64_t The last time we attempted to connect to that peer.
* seconds The last time we attempted to connect to that peer.
*/
std::pair<CAddress, int64_t> SelectTriedCollision();
std::pair<CAddress, NodeSeconds> SelectTriedCollision();

/**
* Choose an address to connect to.
Expand All @@ -164,9 +165,9 @@ class AddrMan
* @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.
* seconds The last time we attempted to connect to that peer.
*/
std::pair<CAddress, int64_t> Select(bool new_only = false, std::optional<Network> network = std::nullopt) const;
std::pair<CAddress, NodeSeconds> Select(bool new_only = false, std::optional<Network> network = std::nullopt) const;

/**
* Return all or many randomly selected addresses, optionally by network.
Expand All @@ -188,9 +189,9 @@ class AddrMan
* not leak information about currently connected peers.
*
* @param[in] addr The address of the peer we were connected to
* @param[in] nTime The time that we were last connected to this peer
* @param[in] time The time that we were last connected to this peer
*/
void Connected(const CService& addr, int64_t nTime = GetAdjustedTime());
void Connected(const CService& addr, NodeSeconds time = AdjustedTime());

//! Update an entry's service bits.
void SetServices(const CService& addr, ServiceFlags nServices);
Expand Down
42 changes: 22 additions & 20 deletions src/addrman_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
#include <protocol.h>
#include <serialize.h>
#include <sync.h>
#include <timedata.h>
#include <uint256.h>
#include <util/time.h>

#include <cstdint>
#include <optional>
Expand All @@ -38,16 +40,16 @@ class AddrInfo : public CAddress
{
public:
//! last try whatsoever by us (memory only)
int64_t nLastTry{0};
NodeSeconds m_last_try{0s};

//! last counted attempt (memory only)
int64_t nLastCountAttempt{0};
NodeSeconds m_last_count_attempt{0s};

//! where knowledge about this address first came from
CNetAddr source;

//! last successful connection by us
int64_t nLastSuccess{0};
NodeSeconds m_last_success{0s};

//! connection attempts since last successful attempt
int nAttempts{0};
Expand All @@ -64,7 +66,7 @@ class AddrInfo : public CAddress
SERIALIZE_METHODS(AddrInfo, obj)
{
READWRITEAS(CAddress, obj);
READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts);
READWRITE(obj.source, Using<ChronoFormatter<int64_t>>(obj.m_last_success), obj.nAttempts);
}

AddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
Expand All @@ -91,10 +93,10 @@ class AddrInfo : public CAddress
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;
bool IsTerrible(NodeSeconds now = AdjustedTime()) const;

//! Calculate the relative chance this entry should be given when selecting nodes to connect to
double GetChance(int64_t nNow = GetAdjustedTime()) const;
double GetChance(NodeSeconds now = AdjustedTime()) const;
};

class AddrManImpl
Expand All @@ -112,26 +114,26 @@ class AddrManImpl

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)
bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
EXCLUSIVE_LOCKS_REQUIRED(!cs);

bool Good(const CService& addr, int64_t nTime)
bool Good(const CService& addr, NodeSeconds time)
EXCLUSIVE_LOCKS_REQUIRED(!cs);

void Attempt(const CService& addr, bool fCountFailure, int64_t nTime)
void Attempt(const CService& addr, bool fCountFailure, NodeSeconds time)
EXCLUSIVE_LOCKS_REQUIRED(!cs);

void ResolveCollisions() EXCLUSIVE_LOCKS_REQUIRED(!cs);

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

std::pair<CAddress, int64_t> Select(bool new_only, std::optional<Network> network) const
std::pair<CAddress, NodeSeconds> 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
EXCLUSIVE_LOCKS_REQUIRED(!cs);

void Connected(const CService& addr, int64_t nTime)
void Connected(const CService& addr, NodeSeconds time)
EXCLUSIVE_LOCKS_REQUIRED(!cs);

void SetServices(const CService& addr, ServiceFlags nServices)
Expand Down Expand Up @@ -205,7 +207,7 @@ class AddrManImpl
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);

//! last time Good was called (memory only). Initially set to 1 so that "never" is strictly worse.
int64_t nLastGood GUARDED_BY(cs){1};
NodeSeconds m_last_good GUARDED_BY(cs){1s};

//! Holds addrs inserted into tried table that collide with existing entries. Test-before-evict discipline used to resolve these collisions.
std::set<int> m_tried_collisions;
Expand Down Expand Up @@ -244,15 +246,15 @@ class AddrManImpl

/** Attempt to add a single address to addrman's new table.
* @see AddrMan::Add() for parameters. */
bool AddSingle(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
bool AddSingle(const CAddress& addr, const CNetAddr& source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs);

bool Good_(const CService& addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
bool Good_(const CService& addr, bool test_before_evict, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);

bool Add_(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
bool Add_(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs);

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

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

/** Helper to generalize looking up an addrman entry from either table.
*
Expand All @@ -262,15 +264,15 @@ class AddrManImpl

std::vector<CAddress> GetAddr_(size_t max_addresses, size_t max_pct, std::optional<Network> network) const EXCLUSIVE_LOCKS_REQUIRED(cs);

void Connected_(const CService& addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
void Connected_(const CService& addr, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);

void SetServices_(const CService& addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);

AddrInfo GetAddressInfo_(const CService& addr) EXCLUSIVE_LOCKS_REQUIRED(cs);

void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);

std::pair<CAddress, int64_t> SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
std::pair<CAddress, NodeSeconds> SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);

std::optional<AddressPosition> FindAddressEntry_(const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(cs);

Expand Down
4 changes: 2 additions & 2 deletions src/bench/addrman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static void CreateAddresses()

CAddress ret(CService(addr, port), NODE_NETWORK);

ret.nTime = GetAdjustedTime();
ret.nTime = AdjustedTime();

return ret;
};
Expand Down Expand Up @@ -118,7 +118,7 @@ static void AddrManSelectByNetwork(benchmark::Bench& bench)
CService i2p_service;
i2p_service.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p");
CAddress i2p_address(i2p_service, NODE_NONE);
i2p_address.nTime = GetAdjustedTime();
i2p_address.nTime = Now<NodeSeconds>();
const CNetAddr source{LookupHost("252.2.2.2", false).value()};
addrman.Add({i2p_address}, source);

Expand Down
18 changes: 9 additions & 9 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,15 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
// it'll get a pile of addresses with newer timestamps.
// Seed nodes are given a random 'last seen time' of between one and two
// weeks ago.
const int64_t nOneWeek = 7*24*60*60;
const auto one_week{7 * 24h};
std::vector<CAddress> vSeedsOut;
FastRandomContext rng;
CDataStream s(vSeedsIn, SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
while (!s.eof()) {
CService endpoint;
s >> endpoint;
CAddress addr{endpoint, GetDesirableServiceFlags(NODE_NONE)};
addr.nTime = GetTime() - rng.randrange(nOneWeek) - nOneWeek;
addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - one_week, -one_week);
LogPrint(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToStringAddrPort());
vSeedsOut.push_back(addr);
}
Expand Down Expand Up @@ -512,11 +512,11 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "trying %s connection %s lastseen=%.1fhrs\n",
use_v2transport ? "v2" : "v1",
pszDest ? pszDest : addrConnect.ToStringAddrPort(),
pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
Ticks<HoursDouble>(pszDest ? 0h : AdjustedTime() - addrConnect.nTime));
} else {
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "trying %s connection lastseen=%.1fhrs\n",
use_v2transport ? "v2" : "v1",
pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
Ticks<HoursDouble>(pszDest ? 0h : AdjustedTime() - addrConnect.nTime));
}

// Resolve
Expand Down Expand Up @@ -3080,9 +3080,8 @@ void CConnman::ThreadDNSAddressSeed()
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
addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - 3 * 24h, -4 * 24h); // use a random age between 3 and 7 days old
vAdd.push_back(addr);
found++;
}
Expand Down Expand Up @@ -3451,7 +3450,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe

auto mnList = dmnman.GetListAtChainTip();

int64_t nANow = GetAdjustedTime();
const auto nANow{AdjustedTime()};
int nTries = 0;
while (!interruptNet)
{
Expand All @@ -3474,7 +3473,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
break;

CAddress addr;
int64_t addr_last_try{0};
NodeSeconds addr_last_try{0s};

if (fFeeler) {
// First, try to get a tried table collision address. This returns
Expand Down Expand Up @@ -3530,8 +3529,9 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
if (onion_only && !addr.IsTor()) continue;

// only consider very recently tried nodes after 30 failed attempts
if (nANow - addr_last_try < 600 && nTries < 30)
if (nANow - addr_last_try < 10min && nTries < 30) {
continue;
}

// for non-feelers, require all the services we'll want,
// for feelers, only require they be a full node (only because most
Expand Down
17 changes: 9 additions & 8 deletions src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <reverse_iterator.h>
#include <scheduler.h>
#include <streams.h>
#include <timedata.h>
#include <tinyformat.h>
#include <index/txindex.h>
#include <txmempool.h>
Expand Down Expand Up @@ -3695,7 +3696,7 @@ void PeerManagerImpl::ProcessMessage(
// indicate to the peer that we will participate in addr relay.
if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload())
{
CAddress addr{GetLocalAddress(pfrom), peer->m_our_services, (uint32_t)GetAdjustedTime()};
CAddress addr{GetLocalAddress(pfrom), peer->m_our_services, AdjustedTime()};
FastRandomContext insecure_rand;
if (addr.IsRoutable())
{
Expand Down Expand Up @@ -3982,8 +3983,7 @@ void PeerManagerImpl::ProcessMessage(

// Store the new addresses
std::vector<CAddress> vAddrOk;
int64_t nNow = GetAdjustedTime();
int64_t nSince = nNow - 10 * 60;
const auto current_a_time{AdjustedTime()};

// Update/increment addr rate limiting bucket.
const auto current_time{GetTime<std::chrono::microseconds>()};
Expand Down Expand Up @@ -4019,16 +4019,17 @@ void PeerManagerImpl::ProcessMessage(
if (!MayHaveUsefulAddressDB(addr.nServices) && !HasAllDesirableServiceFlags(addr.nServices))
continue;

if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
addr.nTime = nNow - 5 * 24 * 60 * 60;
if (addr.nTime <= NodeSeconds{100000000s} || addr.nTime > current_a_time + 10min) {
addr.nTime = current_a_time - 5 * 24h;
}
AddAddressKnown(*peer, addr);
if (m_banman && (m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr))) {
// Do not process banned/discouraged addresses beyond remembering we received them
continue;
}
++num_proc;
bool fReachable = IsReachable(addr);
if (addr.nTime > nSince && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.IsRoutable()) {
if (addr.nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.IsRoutable()) {
// Relay to a limited number of other nodes
RelayAddress(pfrom.GetId(), addr, fReachable);
}
Expand All @@ -4041,7 +4042,7 @@ void PeerManagerImpl::ProcessMessage(
LogPrint(BCLog::NET, "Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
vAddr.size(), num_proc, num_rate_limit, pfrom.GetId());

m_addrman.Add(vAddrOk, pfrom.addr, 2 * 60 * 60);
m_addrman.Add(vAddrOk, pfrom.addr, 2h);
if (vAddr.size() < 1000) peer->m_getaddr_sent = false;

// AddrFetch: Require multiple addresses to avoid disconnecting on self-announcements
Expand Down Expand Up @@ -5667,7 +5668,7 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
peer.m_addr_known->reset();
}
if (std::optional<CService> local_service = GetLocalAddrForPeer(node)) {
CAddress local_addr{*local_service, peer.m_our_services, (uint32_t)GetAdjustedTime()};
CAddress local_addr{*local_service, peer.m_our_services, AdjustedTime()};
FastRandomContext insecure_rand;
PushAddress(peer, local_addr, insecure_rand);
}
Expand Down
1 change: 0 additions & 1 deletion src/node/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
#include <shutdown.h>
#include <support/allocators/secure.h>
#include <sync.h>
#include <timedata.h>
#include <txmempool.h>
#include <uint256.h>
#include <util/check.h>
Expand Down
Loading

0 comments on commit bc3ec30

Please sign in to comment.