Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make all of net_processing (and some of net) use std::chrono types #20044

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 19 additions & 17 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -599,9 +599,9 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
}

// Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :)
stats.m_ping_usec = nPingUsecTime;
stats.m_min_ping_usec = nMinPingUsecTime;
stats.m_ping_wait_usec = count_microseconds(ping_wait);
stats.m_ping_time = m_ping_time;
stats.m_min_ping_time = m_min_ping_time;
stats.m_ping_wait = ping_wait;

// Leave string empty if addrLocal invalid (not filled in yet)
CService addrLocalUnlocked = GetAddrLocal();
Expand Down Expand Up @@ -839,7 +839,7 @@ struct NodeEvictionCandidate
{
NodeId id;
int64_t nTimeConnected;
int64_t nMinPingUsecTime;
std::chrono::microseconds m_min_ping_time;
int64_t nLastBlockTime;
int64_t nLastTXTime;
bool fRelevantServices;
Expand All @@ -853,7 +853,7 @@ struct NodeEvictionCandidate

static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
{
return a.nMinPingUsecTime > b.nMinPingUsecTime;
return a.m_min_ping_time > b.m_min_ping_time;
}

static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
Expand Down Expand Up @@ -934,7 +934,7 @@ bool CConnman::AttemptToEvictConnection()
peer_relay_txes = node->m_tx_relay->fRelayTxes;
peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
}
NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->m_min_ping_time,
node->nLastBlockTime, node->nLastTXTime,
HasAllDesirableServiceFlags(node->nServices),
peer_relay_txes, peer_filter_not_null, node->addr, node->nKeyedNetGroup,
Expand Down Expand Up @@ -1858,10 +1858,10 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
}

// Initiate network connections
int64_t nStart = GetTime();
auto start = GetTime<std::chrono::microseconds>();

// Minimum time before next feeler connection (in microseconds).
int64_t nNextFeeler = PoissonNextSend(nStart*1000*1000, FEELER_INTERVAL);
auto next_feeler = PoissonNextSend(start, FEELER_INTERVAL);
while (!interruptNet)
{
ProcessAddrFetch();
Expand All @@ -1877,7 +1877,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
// Note that we only do this if we started with an empty peers.dat,
// (in which case we will query DNS seeds immediately) *and* the DNS
// seeds have not returned any results.
if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
if (addrman.size() == 0 && (GetTime<std::chrono::microseconds>() - start > std::chrono::minutes{1})) {
static bool done = false;
if (!done) {
LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
Expand Down Expand Up @@ -1923,7 +1923,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
}

ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
int64_t nTime = GetTimeMicros();
auto now = GetTime<std::chrono::microseconds>();
bool fFeeler = false;

// Determine what type of connection to open. Opening
Expand All @@ -1941,8 +1941,8 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
conn_type = ConnectionType::BLOCK_RELAY;
} else if (GetTryNewOutboundPeer()) {
// OUTBOUND_FULL_RELAY
} else if (nTime > nNextFeeler) {
nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL);
} else if (now > next_feeler) {
next_feeler = PoissonNextSend(now, FEELER_INTERVAL);
conn_type = ConnectionType::FEELER;
fFeeler = true;
} else {
Expand Down Expand Up @@ -2954,20 +2954,22 @@ bool CConnman::ForNode(NodeId id, std::function<bool(CNode* pnode)> func)
return found != nullptr && NodeFullyConnected(found) && func(found);
}

int64_t CConnman::PoissonNextSendInbound(int64_t now, int average_interval_seconds)
std::chrono::microseconds CConnman::PoissonNextSendInbound(std::chrono::microseconds now, std::chrono::microseconds average_interval)
{
if (m_next_send_inv_to_incoming < now) {
if (m_next_send_inv_to_incoming.load() < now) {
// If this function were called from multiple threads simultaneously
// it would possible that both update the next send variable, and return a different result to their caller.
// This is not possible in practice as only the net processing thread invokes this function.
m_next_send_inv_to_incoming = PoissonNextSend(now, average_interval_seconds);
m_next_send_inv_to_incoming = PoissonNextSend(now, average_interval);
}
return m_next_send_inv_to_incoming;
}

int64_t PoissonNextSend(int64_t now, int average_interval_seconds)
std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now, std::chrono::microseconds average_interval)
{
return now + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);
double unscaled = log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */);
double scaled = unscaled * count_microseconds(average_interval);
return now + std::chrono::microseconds{int64_t(scaled + 0.5)};
}

CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id) const
Expand Down
28 changes: 11 additions & 17 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ static const bool DEFAULT_WHITELISTFORCERELAY = false;

/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
static const int TIMEOUT_INTERVAL = 20 * 60;
/** Run the feeler connection loop once every 2 minutes or 120 seconds. **/
static const int FEELER_INTERVAL = 120;
/** Run the feeler connection loop once every 2 minutes. **/
static constexpr auto FEELER_INTERVAL = std::chrono::minutes{2};
/** The maximum number of addresses from our addrman to return in response to a getaddr message. */
static constexpr size_t MAX_ADDR_TO_SEND = 1000;
/** Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable). */
Expand Down Expand Up @@ -402,7 +402,7 @@ class CConnman
Works assuming that a single interval is used.
Variable intervals will result in privacy decrease.
*/
int64_t PoissonNextSendInbound(int64_t now, int average_interval_seconds);
std::chrono::microseconds PoissonNextSendInbound(std::chrono::microseconds now, std::chrono::microseconds average_interval);

void SetAsmap(std::vector<bool> asmap) { addrman.m_asmap = std::move(asmap); }

Expand Down Expand Up @@ -584,7 +584,7 @@ class CConnman
* This takes the place of a feeler connection */
std::atomic_bool m_try_another_outbound_peer;

std::atomic<int64_t> m_next_send_inv_to_incoming{0};
std::atomic<std::chrono::microseconds> m_next_send_inv_to_incoming{std::chrono::microseconds{0}};

friend struct CConnmanTest;
friend struct ConnmanTestMsg;
Expand Down Expand Up @@ -704,9 +704,9 @@ class CNodeStats
mapMsgCmdSize mapRecvBytesPerMsgCmd;
NetPermissionFlags m_permissionFlags;
bool m_legacyWhitelisted;
int64_t m_ping_usec;
int64_t m_ping_wait_usec;
int64_t m_min_ping_usec;
std::chrono::microseconds m_ping_time;
std::chrono::microseconds m_ping_wait;
std::chrono::microseconds m_min_ping_time;
CAmount minFeeFilter;
// Our address, as reported by the peer
std::string addrLocal;
Expand Down Expand Up @@ -999,7 +999,7 @@ class CNode
// Minimum fee rate with which to filter inv's to this node
CAmount minFeeFilter GUARDED_BY(cs_feeFilter){0};
CAmount lastSentFeeFilter{0};
int64_t nextSendTimeFeeFilter{0};
std::chrono::microseconds m_next_send_feefilter{0};
};

// m_tx_relay == nullptr if we're not relaying transactions with this peer
Expand Down Expand Up @@ -1027,9 +1027,9 @@ class CNode
/** When the last ping was sent, or 0 if no ping was ever sent */
std::atomic<std::chrono::microseconds> m_ping_start{std::chrono::microseconds{0}};
// Last measured round-trip time.
std::atomic<int64_t> nPingUsecTime{0};
std::atomic<std::chrono::microseconds> m_ping_time{std::chrono::microseconds{0}};
// Best measured round-trip time.
std::atomic<int64_t> nMinPingUsecTime{std::numeric_limits<int64_t>::max()};
std::atomic<std::chrono::microseconds> m_min_ping_time{std::chrono::microseconds::max()};
// Whether a ping is requested.
std::atomic<bool> fPingQueued{false};

Expand Down Expand Up @@ -1177,12 +1177,6 @@ class CNode
};

/** Return a timestamp in the future (in microseconds) for exponentially distributed events. */
int64_t PoissonNextSend(int64_t now, int average_interval_seconds);

/** Wrapper to return mockable type */
inline std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now, std::chrono::seconds average_interval)
{
return std::chrono::microseconds{PoissonNextSend(now.count(), average_interval.count())};
}
std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now, std::chrono::microseconds average_interval);

#endif // BITCOIN_NET_H
Loading