merge bitcoin#21015: Make all of net_processing (and some of net) use std::chrono types

This commit is contained in:
Kittywhiskers Van Gogh 2024-04-03 16:10:14 +00:00
parent 8b204c4c82
commit 62a7311fe4
No known key found for this signature in database
GPG Key ID: 30CD0C065E5C4AAD
13 changed files with 148 additions and 139 deletions

View File

@ -684,8 +684,8 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
X(m_legacyWhitelisted); X(m_legacyWhitelisted);
X(m_permissionFlags); X(m_permissionFlags);
stats.m_ping_usec = m_last_ping_time; X(m_last_ping_time);
stats.m_min_ping_usec = m_min_ping_time; X(m_min_ping_time);
// Leave string empty if addrLocal invalid (not filled in yet) // Leave string empty if addrLocal invalid (not filled in yet)
CService addrLocalUnlocked = GetAddrLocal(); CService addrLocalUnlocked = GetAddrLocal();
@ -1469,8 +1469,9 @@ void CConnman::CalculateNumConnectionsChangedStats()
ipv6Nodes++; ipv6Nodes++;
if(pnode->addr.IsTor()) if(pnode->addr.IsTor())
torNodes++; torNodes++;
if(pnode->m_last_ping_time > 0) const auto last_ping_time = count_microseconds(pnode->m_last_ping_time);
statsClient.timing("peers.ping_us", pnode->m_last_ping_time, 1.0f); if (last_ping_time > 0)
statsClient.timing("peers.ping_us", last_ping_time, 1.0f);
} }
ReleaseNodeVector(vNodesCopy); ReleaseNodeVector(vNodesCopy);
for (const std::string &msg : getAllNetMessageTypes()) { for (const std::string &msg : getAllNetMessageTypes()) {
@ -2283,12 +2284,11 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
} }
// Initiate network connections // Initiate network connections
auto start = GetTime<std::chrono::seconds>(); auto start = GetTime<std::chrono::microseconds>();
// Minimum time before next feeler connection (in microseconds). // Minimum time before next feeler connection (in microseconds).
auto next_feeler = PoissonNextSend(start, FEELER_INTERVAL);
int64_t nNextFeeler = PoissonNextSend(count_microseconds(start), FEELER_INTERVAL); auto next_extra_block_relay = PoissonNextSend(start, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
int64_t nNextExtraBlockRelay = PoissonNextSend(count_microseconds(start), EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
const bool dnsseed = gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED); const bool dnsseed = gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED);
bool add_fixed_seeds = gArgs.GetBoolArg("-fixedseeds", DEFAULT_FIXEDSEEDS); bool add_fixed_seeds = gArgs.GetBoolArg("-fixedseeds", DEFAULT_FIXEDSEEDS);
@ -2382,7 +2382,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
} }
ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY; ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
int64_t nTime = GetTimeMicros(); auto now = GetTime<std::chrono::microseconds>();
bool anchor = false; bool anchor = false;
bool fFeeler = false; bool fFeeler = false;
@ -2394,7 +2394,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
// GetTryNewOutboundPeer() gets set when a stale tip is detected, so we // GetTryNewOutboundPeer() gets set when a stale tip is detected, so we
// try opening an additional OUTBOUND_FULL_RELAY connection. If none of // try opening an additional OUTBOUND_FULL_RELAY connection. If none of
// these conditions are met, check to see if it's time to try an extra // these conditions are met, check to see if it's time to try an extra
// block-relay-only peer (to confirm our tip is current, see below) or the nNextFeeler // block-relay-only peer (to confirm our tip is current, see below) or the next_feeler
// timer to decide if we should open a FEELER. // timer to decide if we should open a FEELER.
if (!m_anchors.empty() && (nOutboundBlockRelay < m_max_outbound_block_relay)) { if (!m_anchors.empty() && (nOutboundBlockRelay < m_max_outbound_block_relay)) {
@ -2406,7 +2406,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
conn_type = ConnectionType::BLOCK_RELAY; conn_type = ConnectionType::BLOCK_RELAY;
} else if (GetTryNewOutboundPeer()) { } else if (GetTryNewOutboundPeer()) {
// OUTBOUND_FULL_RELAY // OUTBOUND_FULL_RELAY
} else if (nTime > nNextExtraBlockRelay && m_start_extra_block_relay_peers) { } else if (now > next_extra_block_relay && m_start_extra_block_relay_peers) {
// Periodically connect to a peer (using regular outbound selection // Periodically connect to a peer (using regular outbound selection
// methodology from addrman) and stay connected long enough to sync // methodology from addrman) and stay connected long enough to sync
// headers, but not much else. // headers, but not much else.
@ -2428,10 +2428,10 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
// Because we can promote these connections to block-relay-only // Because we can promote these connections to block-relay-only
// connections, they do not get their own ConnectionType enum // connections, they do not get their own ConnectionType enum
// (similar to how we deal with extra outbound peers). // (similar to how we deal with extra outbound peers).
nNextExtraBlockRelay = PoissonNextSend(nTime, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL); next_extra_block_relay = PoissonNextSend(now, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
conn_type = ConnectionType::BLOCK_RELAY; conn_type = ConnectionType::BLOCK_RELAY;
} else if (nTime > nNextFeeler) { } else if (now > next_feeler) {
nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL); next_feeler = PoissonNextSend(now, FEELER_INTERVAL);
conn_type = ConnectionType::FEELER; conn_type = ConnectionType::FEELER;
fFeeler = true; fFeeler = true;
} else { } else {
@ -4150,20 +4150,21 @@ bool CConnman::IsMasternodeOrDisconnectRequested(const CService& addr) {
}); });
} }
int64_t CConnman::PoissonNextSendInbound(int64_t now, int average_interval_seconds) std::chrono::microseconds CConnman::PoissonNextSendInbound(std::chrono::microseconds now, std::chrono::seconds 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 // 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. // 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. // 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; 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::seconds 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 */);
return now + std::chrono::duration_cast<std::chrono::microseconds>(unscaled * average_interval + 0.5us);
} }
std::vector<CNode*> CConnman::CopyNodeVector(std::function<bool(const CNode* pnode)> cond) std::vector<CNode*> CConnman::CopyNodeVector(std::function<bool(const CNode* pnode)> cond)

View File

@ -63,12 +63,12 @@ static const int TIMEOUT_INTERVAL = 20 * 60;
static const int PROBE_WAIT_INTERVAL = 5; static const int PROBE_WAIT_INTERVAL = 5;
/** Minimum time between warnings printed to log. */ /** Minimum time between warnings printed to log. */
static const int WARNING_INTERVAL = 10 * 60; static const int WARNING_INTERVAL = 10 * 60;
/** Run the feeler connection loop once every 2 minutes or 120 seconds. **/ /** Run the feeler connection loop once every 2 minutes. **/
static const int FEELER_INTERVAL = 120; static constexpr auto FEELER_INTERVAL = 2min;
/** The maximum number of entries in an 'inv' protocol message */ /** The maximum number of entries in an 'inv' protocol message */
static const unsigned int MAX_INV_SZ = 50000; static const unsigned int MAX_INV_SZ = 50000;
/** Run the extra block-relay-only connection loop once every 5 minutes. **/ /** Run the extra block-relay-only connection loop once every 5 minutes. **/
static const int EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL = 300; static constexpr auto EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL = 5min;
/** The maximum number of addresses from our addrman to return in response to a getaddr message. */ /** 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; static constexpr size_t MAX_ADDR_TO_SEND = 1000;
/** Maximum length of incoming protocol messages (no message over 3 MiB is currently acceptable). */ /** Maximum length of incoming protocol messages (no message over 3 MiB is currently acceptable). */
@ -288,8 +288,8 @@ public:
mapMsgCmdSize mapRecvBytesPerMsgCmd; mapMsgCmdSize mapRecvBytesPerMsgCmd;
NetPermissionFlags m_permissionFlags; NetPermissionFlags m_permissionFlags;
bool m_legacyWhitelisted; bool m_legacyWhitelisted;
int64_t m_ping_usec; std::chrono::microseconds m_last_ping_time;
int64_t m_min_ping_usec; std::chrono::microseconds m_min_ping_time;
// Our address, as reported by the peer // Our address, as reported by the peer
std::string addrLocal; std::string addrLocal;
// Address of this peer // Address of this peer
@ -646,11 +646,11 @@ public:
std::atomic<int64_t> nLastTXTime{0}; std::atomic<int64_t> nLastTXTime{0};
/** Last measured round-trip time. Used only for RPC/GUI stats/debugging.*/ /** Last measured round-trip time. Used only for RPC/GUI stats/debugging.*/
std::atomic<int64_t> m_last_ping_time{0}; std::atomic<std::chrono::microseconds> m_last_ping_time{0us};
/** Lowest measured round-trip time. Used as an inbound peer eviction /** Lowest measured round-trip time. Used as an inbound peer eviction
* criterium in CConnman::AttemptToEvictConnection. */ * criterium in CConnman::AttemptToEvictConnection. */
std::atomic<int64_t> m_min_ping_time{std::numeric_limits<int64_t>::max()}; std::atomic<std::chrono::microseconds> m_min_ping_time{std::chrono::microseconds::max()};
// If true, we will send him CoinJoin queue messages // If true, we will send him CoinJoin queue messages
std::atomic<bool> fSendDSQueue{false}; std::atomic<bool> fSendDSQueue{false};
@ -838,8 +838,8 @@ public:
/** A ping-pong round trip has completed successfully. Update latest and minimum ping times. */ /** A ping-pong round trip has completed successfully. Update latest and minimum ping times. */
void PongReceived(std::chrono::microseconds ping_time) { void PongReceived(std::chrono::microseconds ping_time) {
m_last_ping_time = count_microseconds(ping_time); m_last_ping_time = ping_time;
m_min_ping_time = std::min(m_min_ping_time.load(), count_microseconds(ping_time)); m_min_ping_time = std::min(m_min_ping_time.load(), ping_time);
} }
/** Whether this peer is an inbound onion, e.g. connected via our Tor onion service. */ /** Whether this peer is an inbound onion, e.g. connected via our Tor onion service. */
@ -1300,7 +1300,7 @@ public:
Works assuming that a single interval is used. Works assuming that a single interval is used.
Variable intervals will result in privacy decrease. 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::seconds average_interval);
void SetAsmap(std::vector<bool> asmap) { addrman.m_asmap = std::move(asmap); } void SetAsmap(std::vector<bool> asmap) { addrman.m_asmap = std::move(asmap); }
@ -1579,7 +1579,7 @@ private:
*/ */
std::atomic_bool m_start_extra_block_relay_peers{false}; std::atomic_bool m_start_extra_block_relay_peers{false};
std::atomic<int64_t> m_next_send_inv_to_incoming{0}; std::atomic<std::chrono::microseconds> m_next_send_inv_to_incoming{0us};
/** /**
* A vector of -bind=<address>:<port>=onion arguments each of which is * A vector of -bind=<address>:<port>=onion arguments each of which is
@ -1592,13 +1592,7 @@ private:
}; };
/** Return a timestamp in the future (in microseconds) for exponentially distributed events. */ /** Return a timestamp in the future (in microseconds) for exponentially distributed events. */
int64_t PoissonNextSend(int64_t now, int average_interval_seconds); std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now, std::chrono::seconds average_interval);
/** 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())};
}
/** Dump binary message to file, with timestamp */ /** Dump binary message to file, with timestamp */
void CaptureMessage(const CAddress& addr, const std::string& msg_type, const Span<const unsigned char>& data, bool is_incoming); void CaptureMessage(const CAddress& addr, const std::string& msg_type, const Span<const unsigned char>& data, bool is_incoming);
@ -1607,7 +1601,7 @@ struct NodeEvictionCandidate
{ {
NodeId id; NodeId id;
int64_t nTimeConnected; int64_t nTimeConnected;
int64_t m_min_ping_time; std::chrono::microseconds m_min_ping_time;
int64_t nLastBlockTime; int64_t nLastBlockTime;
int64_t nLastTXTime; int64_t nLastTXTime;
bool fRelevantServices; bool fRelevantServices;

View File

@ -87,13 +87,13 @@ static constexpr int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60;
/** Minimum time between orphan transactions expire time checks in seconds */ /** Minimum time between orphan transactions expire time checks in seconds */
static constexpr int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60; static constexpr int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60;
/** How long to cache transactions in mapRelay for normal relay */ /** How long to cache transactions in mapRelay for normal relay */
static constexpr std::chrono::seconds RELAY_TX_CACHE_TIME = std::chrono::minutes{15}; static constexpr auto RELAY_TX_CACHE_TIME = 15min;
/** How long a transaction has to be in the mempool before it can unconditionally be relayed (even when not in mapRelay). */ /** How long a transaction has to be in the mempool before it can unconditionally be relayed (even when not in mapRelay). */
static constexpr std::chrono::seconds UNCONDITIONAL_RELAY_DELAY = std::chrono::minutes{2}; static constexpr auto UNCONDITIONAL_RELAY_DELAY = 2min;
/** Headers download timeout expressed in microseconds /** Headers download timeout.
* Timeout = base + per_header * (expected number of headers) */ * Timeout = base + per_header * (expected number of headers) */
static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE = 15min;
static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER = 1000; // 1ms/header static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER = 1ms;
/** Protect at least this many outbound peers from disconnection due to slow/ /** Protect at least this many outbound peers from disconnection due to slow/
* behind headers chain. * behind headers chain.
*/ */
@ -120,8 +120,8 @@ static constexpr std::chrono::minutes PING_INTERVAL{2};
static const unsigned int MAX_LOCATOR_SZ = 101; static const unsigned int MAX_LOCATOR_SZ = 101;
/** Number of blocks that can be requested at any given time from a single peer. */ /** Number of blocks that can be requested at any given time from a single peer. */
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16; static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
/** Timeout in seconds during which a peer must stall block download progress before being disconnected. */ /** Time during which a peer must stall block download progress before being disconnected. */
static const unsigned int BLOCK_STALLING_TIMEOUT = 2; static constexpr auto BLOCK_STALLING_TIMEOUT = 2s;
/** Maximum depth of blocks we're willing to serve as compact blocks to peers /** Maximum depth of blocks we're willing to serve as compact blocks to peers
* when requested. For older blocks, a regular BLOCK response will be sent. */ * when requested. For older blocks, a regular BLOCK response will be sent. */
static const int MAX_CMPCTBLOCK_DEPTH = 5; static const int MAX_CMPCTBLOCK_DEPTH = 5;
@ -132,31 +132,34 @@ static const int MAX_BLOCKTXN_DEPTH = 10;
* degree of disordering of blocks on disk (which make reindexing and pruning harder). We'll probably * degree of disordering of blocks on disk (which make reindexing and pruning harder). We'll probably
* want to make this a per-peer adaptive value at some point. */ * want to make this a per-peer adaptive value at some point. */
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024; static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
/** Block download timeout base, expressed in millionths of the block interval (i.e. 10 min) */ /** Block download timeout base, expressed in multiples of the block interval (i.e. 10 min) */
static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000; static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE = 1;
/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */ /** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000; static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 0.5;
/** Maximum number of headers to announce when relaying blocks with headers message.*/ /** Maximum number of headers to announce when relaying blocks with headers message.*/
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8; static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
/** Maximum number of unconnecting headers announcements before DoS score */ /** Maximum number of unconnecting headers announcements before DoS score */
static const int MAX_UNCONNECTING_HEADERS = 10; static const int MAX_UNCONNECTING_HEADERS = 10;
/** Minimum blocks required to signal NODE_NETWORK_LIMITED */ /** Minimum blocks required to signal NODE_NETWORK_LIMITED */
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288; static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS = 288;
/** Average delay between local address broadcasts */
/** Average delay between local address broadcasts in seconds. */ static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24h;
static constexpr std::chrono::hours AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL{24}; /** Average delay between peer address broadcasts */
/** Average delay between peer address broadcasts in seconds. */ static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL = 30s;
static constexpr std::chrono::seconds AVG_ADDRESS_BROADCAST_INTERVAL{30}; /** Average delay between trickled inventory transmissions for inbound peers.
/** Average delay between trickled inventory transmissions in seconds. * Blocks and peers with noban permission bypass this. */
* Blocks and peers with noban permission bypass this, regular outbound peers get half this delay, static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL = 5s;
* Masternode outbound peers get quarter this delay. */ /** Average delay between trickled inventory transmissions for outbound peers.
static const unsigned int INVENTORY_BROADCAST_INTERVAL = 5; * Use a smaller delay as there is less privacy concern for them.
* Blocks and peers with noban permission bypass this.
* Masternode outbound peers get half this delay. */
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL = 2s;
/** Maximum rate of inventory items to send per second. /** Maximum rate of inventory items to send per second.
* Limits the impact of low-fee transaction floods. * Limits the impact of low-fee transaction floods.
* We have 4 times smaller block times in Dash, so we need to push 4 times more invs per 1MB. */ * We have 4 times smaller block times in Dash, so we need to push 4 times more invs per 1MB. */
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND = 7; static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND = 7;
/** Maximum number of inventory items to send per transmission. */ /** Maximum number of inventory items to send per transmission. */
static constexpr unsigned int INVENTORY_BROADCAST_MAX_PER_1MB_BLOCK = 4 * INVENTORY_BROADCAST_PER_SECOND * INVENTORY_BROADCAST_INTERVAL; static constexpr unsigned int INVENTORY_BROADCAST_MAX_PER_1MB_BLOCK = 4 * INVENTORY_BROADCAST_PER_SECOND * count_seconds(INBOUND_INVENTORY_BROADCAST_INTERVAL);
/** The number of most recently announced transactions a peer can request. */ /** The number of most recently announced transactions a peer can request. */
static constexpr unsigned int INVENTORY_MAX_RECENT_RELAY = 3500; static constexpr unsigned int INVENTORY_MAX_RECENT_RELAY = 3500;
/** Verify that INVENTORY_MAX_RECENT_RELAY is enough to cache everything typically /** Verify that INVENTORY_MAX_RECENT_RELAY is enough to cache everything typically
@ -564,7 +567,7 @@ private:
typedef std::map<uint256, CTransactionRef> MapRelay; typedef std::map<uint256, CTransactionRef> MapRelay;
MapRelay mapRelay GUARDED_BY(cs_main); MapRelay mapRelay GUARDED_BY(cs_main);
/** Expiration-time ordered list of (expire time, relay map entry) pairs. */ /** Expiration-time ordered list of (expire time, relay map entry) pairs. */
std::deque<std::pair<int64_t, MapRelay::iterator>> vRelayExpiration GUARDED_BY(cs_main); std::deque<std::pair<std::chrono::microseconds, MapRelay::iterator>> g_relay_expiration GUARDED_BY(cs_main);
/** /**
* When a peer sends us a valid block, instruct it to announce blocks to us * When a peer sends us a valid block, instruct it to announce blocks to us
@ -633,12 +636,12 @@ struct CNodeState {
//! Whether we've started headers synchronization with this peer. //! Whether we've started headers synchronization with this peer.
bool fSyncStarted; bool fSyncStarted;
//! When to potentially disconnect peer for stalling headers download //! When to potentially disconnect peer for stalling headers download
int64_t nHeadersSyncTimeout; std::chrono::microseconds m_headers_sync_timeout{0us};
//! Since when we're stalling block download progress (in microseconds), or 0. //! Since when we're stalling block download progress (in microseconds), or 0.
int64_t nStallingSince; std::chrono::microseconds m_stalling_since{0us};
std::list<QueuedBlock> vBlocksInFlight; std::list<QueuedBlock> vBlocksInFlight;
//! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty. //! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty.
int64_t nDownloadingSince; std::chrono::microseconds m_downloading_since{0us};
int nBlocksInFlight; int nBlocksInFlight;
int nBlocksInFlightValidHeaders; int nBlocksInFlightValidHeaders;
//! Whether we consider this a preferred download peer. //! Whether we consider this a preferred download peer.
@ -775,9 +778,6 @@ struct CNodeState {
pindexBestHeaderSent = nullptr; pindexBestHeaderSent = nullptr;
nUnconnectingHeaders = 0; nUnconnectingHeaders = 0;
fSyncStarted = false; fSyncStarted = false;
nHeadersSyncTimeout = 0;
nStallingSince = 0;
nDownloadingSince = 0;
nBlocksInFlight = 0; nBlocksInFlight = 0;
nBlocksInFlightValidHeaders = 0; nBlocksInFlightValidHeaders = 0;
fPreferredDownload = false; fPreferredDownload = false;
@ -829,11 +829,11 @@ bool PeerManagerImpl::MarkBlockAsReceived(const uint256& hash)
} }
if (state->vBlocksInFlight.begin() == itInFlight->second.second) { if (state->vBlocksInFlight.begin() == itInFlight->second.second) {
// First block on the queue was received, update the start download time for the next one // First block on the queue was received, update the start download time for the next one
state->nDownloadingSince = std::max(state->nDownloadingSince, count_microseconds(GetTime<std::chrono::microseconds>())); state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
} }
state->vBlocksInFlight.erase(itInFlight->second.second); state->vBlocksInFlight.erase(itInFlight->second.second);
state->nBlocksInFlight--; state->nBlocksInFlight--;
state->nStallingSince = 0; state->m_stalling_since = 0us;
mapBlocksInFlight.erase(itInFlight); mapBlocksInFlight.erase(itInFlight);
return true; return true;
} }
@ -863,7 +863,7 @@ bool PeerManagerImpl::MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, co
state->nBlocksInFlightValidHeaders += it->fValidatedHeaders; state->nBlocksInFlightValidHeaders += it->fValidatedHeaders;
if (state->nBlocksInFlight == 1) { if (state->nBlocksInFlight == 1) {
// We're starting a block download (batch) from this peer. // We're starting a block download (batch) from this peer.
state->nDownloadingSince = GetTime<std::chrono::microseconds>().count(); state->m_downloading_since = GetTime<std::chrono::microseconds>();
} }
if (state->nBlocksInFlightValidHeaders == 1 && pindex != nullptr) { if (state->nBlocksInFlightValidHeaders == 1 && pindex != nullptr) {
nPeersWithValidatedDownloads++; nPeersWithValidatedDownloads++;
@ -1378,7 +1378,7 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats)
ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load(); ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
} }
stats.m_ping_wait_usec = count_microseconds(ping_wait); stats.m_ping_wait = ping_wait;
return true; return true;
} }
@ -3449,7 +3449,13 @@ void PeerManagerImpl::ProcessMessage(
if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) { if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) {
// Make sure to mark this peer as the one we are currently syncing with etc. // Make sure to mark this peer as the one we are currently syncing with etc.
state->fSyncStarted = true; state->fSyncStarted = true;
state->nHeadersSyncTimeout = GetTimeMicros() + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * (GetAdjustedTime() - pindexBestHeader->GetBlockTime())/(m_chainparams.GetConsensus().nPowTargetSpacing); state->m_headers_sync_timeout = current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE +
(
// Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to microseconds before scaling
// to maintain precision
std::chrono::microseconds{HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER} *
(GetAdjustedTime() - pindexBestHeader->GetBlockTime()) / m_chainparams.GetConsensus().nPowTargetSpacing
);
nSyncStarted++; nSyncStarted++;
// Headers-first is the primary method of announcement on // Headers-first is the primary method of announcement on
// the network. If a node fell back to sending blocks by inv, // the network. If a node fell back to sending blocks by inv,
@ -5025,7 +5031,13 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// Only actively request headers from a single peer, unless we're close to end of initial download. // Only actively request headers from a single peer, unless we're close to end of initial download.
if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) { if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - nMaxTipAge) {
state.fSyncStarted = true; state.fSyncStarted = true;
state.nHeadersSyncTimeout = count_microseconds(current_time) + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * (GetAdjustedTime() - pindexBestHeader->GetBlockTime())/(consensusParams.nPowTargetSpacing); state.m_headers_sync_timeout = current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE +
(
// Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to microseconds before scaling
// to maintain precision
std::chrono::microseconds{HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER} *
(GetAdjustedTime() - pindexBestHeader->GetBlockTime()) / consensusParams.nPowTargetSpacing
);
nSyncStarted++; nSyncStarted++;
const CBlockIndex *pindexStart = pindexBestHeader; const CBlockIndex *pindexStart = pindexBestHeader;
/* If possible, start at the block preceding the currently /* If possible, start at the block preceding the currently
@ -5246,11 +5258,12 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
if (pto->m_tx_relay->nNextInvSend < current_time) { if (pto->m_tx_relay->nNextInvSend < current_time) {
fSendTrickle = true; fSendTrickle = true;
if (pto->IsInboundConn()) { if (pto->IsInboundConn()) {
pto->m_tx_relay->nNextInvSend = std::chrono::microseconds{m_connman.PoissonNextSendInbound(count_microseconds(current_time), INVENTORY_BROADCAST_INTERVAL)}; pto->m_tx_relay->nNextInvSend = m_connman.PoissonNextSendInbound(current_time, INBOUND_INVENTORY_BROADCAST_INTERVAL);
} else { } else {
// Use half the delay for regular outbound peers, as there is less privacy concern for them. // Use half the delay for Masternode outbound peers, as there is less privacy concern for them.
// and quarter the delay for Masternode outbound peers, as there is even less privacy concern in this case. pto->m_tx_relay->nNextInvSend = pto->GetVerifiedProRegTxHash().IsNull() ?
pto->m_tx_relay->nNextInvSend = PoissonNextSend(current_time, std::chrono::seconds{INVENTORY_BROADCAST_INTERVAL >> 1 >> !pto->GetVerifiedProRegTxHash().IsNull()}); PoissonNextSend(current_time, OUTBOUND_INVENTORY_BROADCAST_INTERVAL) :
PoissonNextSend(current_time, OUTBOUND_INVENTORY_BROADCAST_INTERVAL / 2);
} }
} }
@ -5332,15 +5345,15 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
nRelayedTransactions++; nRelayedTransactions++;
{ {
// Expire old relay messages // Expire old relay messages
while (!vRelayExpiration.empty() && vRelayExpiration.front().first < count_microseconds(current_time)) while (!g_relay_expiration.empty() && g_relay_expiration.front().first < current_time)
{ {
mapRelay.erase(vRelayExpiration.front().second); mapRelay.erase(g_relay_expiration.front().second);
vRelayExpiration.pop_front(); g_relay_expiration.pop_front();
} }
auto ret = mapRelay.emplace(hash, std::move(txinfo.tx)); auto ret = mapRelay.emplace(hash, std::move(txinfo.tx));
if (ret.second) { if (ret.second) {
vRelayExpiration.emplace_back(count_microseconds(current_time + std::chrono::microseconds{RELAY_TX_CACHE_TIME}), ret.first); g_relay_expiration.emplace_back(current_time + RELAY_TX_CACHE_TIME, ret.first);
} }
} }
int nInvType = m_cj_ctx->dstxman->GetDSTX(hash) ? MSG_DSTX : MSG_TX; int nInvType = m_cj_ctx->dstxman->GetDSTX(hash) ? MSG_DSTX : MSG_TX;
@ -5375,7 +5388,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// Detect whether we're stalling // Detect whether we're stalling
current_time = GetTime<std::chrono::microseconds>(); current_time = GetTime<std::chrono::microseconds>();
if (state.nStallingSince && state.nStallingSince < count_microseconds(current_time) - 1000000 * BLOCK_STALLING_TIMEOUT) { if (state.m_stalling_since.count() && state.m_stalling_since < current_time - BLOCK_STALLING_TIMEOUT) {
// Stalling only triggers when the block download window cannot move. During normal steady state, // Stalling only triggers when the block download window cannot move. During normal steady state,
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection // the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
// should only happen during initial block download. // should only happen during initial block download.
@ -5383,7 +5396,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
pto->fDisconnect = true; pto->fDisconnect = true;
return true; return true;
} }
// In case there is a block that has been in flight from this peer for 2 + 0.5 * N times the block interval // In case there is a block that has been in flight from this peer for block_interval * (1 + 0.5 * N)
// (with N the number of peers from which we're downloading validated blocks), disconnect due to timeout. // (with N the number of peers from which we're downloading validated blocks), disconnect due to timeout.
// We compensate for other peers to prevent killing off peers due to our own downstream link // We compensate for other peers to prevent killing off peers due to our own downstream link
// being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes // being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes
@ -5391,17 +5404,17 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
if (state.vBlocksInFlight.size() > 0) { if (state.vBlocksInFlight.size() > 0) {
QueuedBlock &queuedBlock = state.vBlocksInFlight.front(); QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0); int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
if (count_microseconds(current_time) > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) { if (current_time > state.m_downloading_since + std::chrono::seconds{consensusParams.nPowTargetSpacing} * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->GetId()); LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->GetId());
pto->fDisconnect = true; pto->fDisconnect = true;
return true; return true;
} }
} }
// Check for headers sync timeouts // Check for headers sync timeouts
if (state.fSyncStarted && state.nHeadersSyncTimeout < std::numeric_limits<int64_t>::max()) { if (state.fSyncStarted && state.m_headers_sync_timeout < std::chrono::microseconds::max()) {
// Detect whether this is a stalling initial-headers-sync peer // Detect whether this is a stalling initial-headers-sync peer
if (pindexBestHeader->GetBlockTime() <= GetAdjustedTime() - nMaxTipAge) { if (pindexBestHeader->GetBlockTime() <= GetAdjustedTime() - nMaxTipAge) {
if (count_microseconds(current_time) > state.nHeadersSyncTimeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1)) { if (current_time > state.m_headers_sync_timeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1)) {
// Disconnect a peer (without the noban permission) if it is our only sync peer, // Disconnect a peer (without the noban permission) if it is our only sync peer,
// and we have others we could be using instead. // and we have others we could be using instead.
// Note: If all our peers are inbound, then we won't // Note: If all our peers are inbound, then we won't
@ -5420,13 +5433,13 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// this peer (eventually). // this peer (eventually).
state.fSyncStarted = false; state.fSyncStarted = false;
nSyncStarted--; nSyncStarted--;
state.nHeadersSyncTimeout = 0; state.m_headers_sync_timeout = 0us;
} }
} }
} else { } else {
// After we've caught up once, reset the timeout so we can't trigger // After we've caught up once, reset the timeout so we can't trigger
// disconnect later. // disconnect later.
state.nHeadersSyncTimeout = std::numeric_limits<int64_t>::max(); state.m_headers_sync_timeout = std::chrono::microseconds::max();
} }
} }
@ -5449,8 +5462,8 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
pindex->nHeight, pto->GetId()); pindex->nHeight, pto->GetId());
} }
if (state.nBlocksInFlight == 0 && staller != -1) { if (state.nBlocksInFlight == 0 && staller != -1) {
if (State(staller)->nStallingSince == 0) { if (State(staller)->m_stalling_since == 0us) {
State(staller)->nStallingSince = count_microseconds(current_time); State(staller)->m_stalling_since = current_time;
LogPrint(BCLog::NET, "Stall started peer=%d\n", staller); LogPrint(BCLog::NET, "Stall started peer=%d\n", staller);
} }
} }

View File

@ -39,7 +39,7 @@ struct CNodeStateStats {
int nSyncHeight = -1; int nSyncHeight = -1;
int nCommonHeight = -1; int nCommonHeight = -1;
int m_starting_height = -1; int m_starting_height = -1;
int64_t m_ping_wait_usec; std::chrono::microseconds m_ping_wait;
std::vector<int> vHeightInFlight; std::vector<int> vHeightInFlight;
}; };

View File

@ -70,6 +70,8 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QtGlobal> #include <QtGlobal>
#include <chrono>
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
#include <QProcess> #include <QProcess>
@ -1687,9 +1689,11 @@ QString formatServicesStr(quint64 mask)
return QObject::tr("None"); return QObject::tr("None");
} }
QString formatPingTime(int64_t ping_usec) QString formatPingTime(std::chrono::microseconds ping_time)
{ {
return (ping_usec == std::numeric_limits<int64_t>::max() || ping_usec == 0) ? QObject::tr("N/A") : QString(QObject::tr("%1 ms")).arg(QString::number((int)(ping_usec / 1000), 10)); return (ping_time == std::chrono::microseconds::max() || ping_time == 0us) ?
QObject::tr("N/A") :
QString(QObject::tr("%1 ms")).arg(QString::number((int)(count_microseconds(ping_time) / 1000), 10));
} }
QString formatTimeOffset(int64_t nTimeOffset) QString formatTimeOffset(int64_t nTimeOffset)

View File

@ -20,6 +20,8 @@
#include <QTableView> #include <QTableView>
#include <QLabel> #include <QLabel>
#include <chrono>
class QValidatedLineEdit; class QValidatedLineEdit;
class OptionsModel; class OptionsModel;
class SendCoinsRecipient; class SendCoinsRecipient;
@ -395,8 +397,8 @@ namespace GUIUtil
/** Format CNodeStats.nServices bitmask into a user-readable string */ /** Format CNodeStats.nServices bitmask into a user-readable string */
QString formatServicesStr(quint64 mask); QString formatServicesStr(quint64 mask);
/** Format a CNodeStats.m_ping_usec into a user-readable string or display N/A, if 0 */ /** Format a CNodeStats.m_last_ping_time into a user-readable string or display N/A, if 0 */
QString formatPingTime(int64_t ping_usec); QString formatPingTime(std::chrono::microseconds ping_time);
/** Format a CNodeCombinedStats.nTimeOffset into a user-readable string */ /** Format a CNodeCombinedStats.nTimeOffset into a user-readable string */
QString formatTimeOffset(int64_t nTimeOffset); QString formatTimeOffset(int64_t nTimeOffset);

View File

@ -32,7 +32,7 @@ bool NodeLessThan::operator()(const CNodeCombinedStats &left, const CNodeCombine
case PeerTableModel::Network: case PeerTableModel::Network:
return pLeft->m_network < pRight->m_network; return pLeft->m_network < pRight->m_network;
case PeerTableModel::Ping: case PeerTableModel::Ping:
return pLeft->m_min_ping_usec < pRight->m_min_ping_usec; return pLeft->m_min_ping_time < pRight->m_min_ping_time;
case PeerTableModel::Sent: case PeerTableModel::Sent:
return pLeft->nSendBytes < pRight->nSendBytes; return pLeft->nSendBytes < pRight->nSendBytes;
case PeerTableModel::Received: case PeerTableModel::Received:
@ -167,7 +167,7 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const
case Network: case Network:
return GUIUtil::NetworkToQString(rec->nodeStats.m_network); return GUIUtil::NetworkToQString(rec->nodeStats.m_network);
case Ping: case Ping:
return GUIUtil::formatPingTime(rec->nodeStats.m_min_ping_usec); return GUIUtil::formatPingTime(rec->nodeStats.m_min_ping_time);
case Sent: case Sent:
return GUIUtil::formatBytes(rec->nodeStats.nSendBytes); return GUIUtil::formatBytes(rec->nodeStats.nSendBytes);
case Received: case Received:

View File

@ -1252,8 +1252,8 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats)
ui->peerLastRecv->setText(TimeDurationField(time_now, stats->nodeStats.nLastRecv)); ui->peerLastRecv->setText(TimeDurationField(time_now, stats->nodeStats.nLastRecv));
ui->peerBytesSent->setText(GUIUtil::formatBytes(stats->nodeStats.nSendBytes)); ui->peerBytesSent->setText(GUIUtil::formatBytes(stats->nodeStats.nSendBytes));
ui->peerBytesRecv->setText(GUIUtil::formatBytes(stats->nodeStats.nRecvBytes)); ui->peerBytesRecv->setText(GUIUtil::formatBytes(stats->nodeStats.nRecvBytes));
ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.m_ping_usec)); ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.m_last_ping_time));
ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.m_min_ping_usec)); ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.m_min_ping_time));
ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset)); ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset));
ui->peerVersion->setText(QString::number(stats->nodeStats.nVersion)); ui->peerVersion->setText(QString::number(stats->nodeStats.nVersion));
ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer)); ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
@ -1302,7 +1302,7 @@ void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats)
ui->peerCommonHeight->setText(tr("Unknown")); ui->peerCommonHeight->setText(tr("Unknown"));
ui->peerHeight->setText(QString::number(stats->nodeStateStats.m_starting_height)); ui->peerHeight->setText(QString::number(stats->nodeStateStats.m_starting_height));
ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStateStats.m_ping_wait_usec)); ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStateStats.m_ping_wait));
} }
ui->detailWidget->show(); ui->detailWidget->show();

View File

@ -213,14 +213,14 @@ static RPCHelpMan getpeerinfo()
obj.pushKV("bytesrecv", stats.nRecvBytes); obj.pushKV("bytesrecv", stats.nRecvBytes);
obj.pushKV("conntime", stats.nTimeConnected); obj.pushKV("conntime", stats.nTimeConnected);
obj.pushKV("timeoffset", stats.nTimeOffset); obj.pushKV("timeoffset", stats.nTimeOffset);
if (stats.m_ping_usec > 0) { if (stats.m_last_ping_time > 0us) {
obj.pushKV("pingtime", ((double)stats.m_ping_usec) / 1e6); obj.pushKV("pingtime", CountSecondsDouble(stats.m_last_ping_time));
} }
if (stats.m_min_ping_usec < std::numeric_limits<int64_t>::max()) { if (stats.m_min_ping_time < std::chrono::microseconds::max()) {
obj.pushKV("minping", ((double)stats.m_min_ping_usec) / 1e6); obj.pushKV("minping", CountSecondsDouble(stats.m_min_ping_time));
} }
if (fStateStats && statestats.m_ping_wait_usec > 0) { if (fStateStats && statestats.m_ping_wait > 0s) {
obj.pushKV("pingwait", ((double)statestats.m_ping_wait_usec) / 1e6); obj.pushKV("pingwait", CountSecondsDouble(statestats.m_ping_wait));
} }
obj.pushKV("version", stats.nVersion); obj.pushKV("version", stats.nVersion);
// Use the sanitized form of subver here, to avoid tricksy remote peers from // Use the sanitized form of subver here, to avoid tricksy remote peers from

View File

@ -93,7 +93,9 @@ FUZZ_TARGET_INIT(connman, initialize_connman)
}, },
[&] { [&] {
// Limit now to int32_t to avoid signed integer overflow // Limit now to int32_t to avoid signed integer overflow
(void)connman.PoissonNextSendInbound(fuzzed_data_provider.ConsumeIntegral<int32_t>(), fuzzed_data_provider.ConsumeIntegral<int>()); (void)connman.PoissonNextSendInbound(
std::chrono::microseconds{fuzzed_data_provider.ConsumeIntegral<int32_t>()},
std::chrono::seconds{fuzzed_data_provider.ConsumeIntegral<int>()});
}, },
[&] { [&] {
CSerializedNetMsg serialized_net_msg; CSerializedNetMsg serialized_net_msg;

View File

@ -20,17 +20,17 @@ FUZZ_TARGET(node_eviction)
std::vector<NodeEvictionCandidate> eviction_candidates; std::vector<NodeEvictionCandidate> eviction_candidates;
while (fuzzed_data_provider.ConsumeBool()) { while (fuzzed_data_provider.ConsumeBool()) {
eviction_candidates.push_back({ eviction_candidates.push_back({
fuzzed_data_provider.ConsumeIntegral<NodeId>(), /* id */ fuzzed_data_provider.ConsumeIntegral<NodeId>(),
fuzzed_data_provider.ConsumeIntegral<int64_t>(), /* nTimeConnected */ fuzzed_data_provider.ConsumeIntegral<int64_t>(),
fuzzed_data_provider.ConsumeIntegral<int64_t>(), /* m_min_ping_time */ std::chrono::microseconds{fuzzed_data_provider.ConsumeIntegral<int64_t>()},
fuzzed_data_provider.ConsumeIntegral<int64_t>(), /* nLastBlockTime */ fuzzed_data_provider.ConsumeIntegral<int64_t>(),
fuzzed_data_provider.ConsumeIntegral<int64_t>(), /* nLastTXTime */ fuzzed_data_provider.ConsumeIntegral<int64_t>(),
fuzzed_data_provider.ConsumeBool(), /* fRelevantServices */ fuzzed_data_provider.ConsumeBool(),
fuzzed_data_provider.ConsumeBool(), /* fRelayTxes */ fuzzed_data_provider.ConsumeBool(),
fuzzed_data_provider.ConsumeBool(), /* fBloomFilter */ fuzzed_data_provider.ConsumeBool(),
fuzzed_data_provider.ConsumeIntegral<uint64_t>(), /* nKeyedNetGroup */ fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
fuzzed_data_provider.ConsumeBool(), /* prefer_evict */ fuzzed_data_provider.ConsumeBool(),
fuzzed_data_provider.ConsumeBool(), /* m_is_local */ fuzzed_data_provider.ConsumeBool(),
}); });
} }
// Make a copy since eviction_candidates may be in some valid but otherwise // Make a copy since eviction_candidates may be in some valid but otherwise

View File

@ -250,20 +250,6 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
BOOST_CHECK_EQUAL(pnode4->ConnectedThroughNetwork(), Network::NET_ONION); BOOST_CHECK_EQUAL(pnode4->ConnectedThroughNetwork(), Network::NET_ONION);
} }
BOOST_AUTO_TEST_CASE(PoissonNextSend)
{
g_mock_deterministic_tests = true;
int64_t now = 5000;
int average_interval_seconds = 600;
auto poisson = ::PoissonNextSend(now, average_interval_seconds);
std::chrono::microseconds poisson_chrono = ::PoissonNextSend(std::chrono::microseconds{now}, std::chrono::seconds{average_interval_seconds});
BOOST_CHECK_EQUAL(poisson, poisson_chrono.count());
g_mock_deterministic_tests = false;
}
BOOST_AUTO_TEST_CASE(cnetaddr_basic) BOOST_AUTO_TEST_CASE(cnetaddr_basic)
{ {
CNetAddr addr; CNetAddr addr;
@ -854,7 +840,7 @@ std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(const int n_c
candidates.push_back({ candidates.push_back({
/* id */ id, /* id */ id,
/* nTimeConnected */ static_cast<int64_t>(random_context.randrange(100)), /* nTimeConnected */ static_cast<int64_t>(random_context.randrange(100)),
/* m_min_ping_time */ static_cast<int64_t>(random_context.randrange(100)), /* m_min_ping_time */ std::chrono::microseconds{random_context.randrange(100)},
/* nLastBlockTime */ static_cast<int64_t>(random_context.randrange(100)), /* nLastBlockTime */ static_cast<int64_t>(random_context.randrange(100)),
/* nLastTXTime */ static_cast<int64_t>(random_context.randrange(100)), /* nLastTXTime */ static_cast<int64_t>(random_context.randrange(100)),
/* fRelevantServices */ random_context.randbool(), /* fRelevantServices */ random_context.randbool(),
@ -914,7 +900,7 @@ BOOST_AUTO_TEST_CASE(node_eviction_test)
// from eviction. // from eviction.
BOOST_CHECK(!IsEvicted( BOOST_CHECK(!IsEvicted(
number_of_nodes, [](NodeEvictionCandidate& candidate) { number_of_nodes, [](NodeEvictionCandidate& candidate) {
candidate.m_min_ping_time = candidate.id; candidate.m_min_ping_time = std::chrono::microseconds{candidate.id};
}, },
{0, 1, 2, 3, 4, 5, 6, 7}, random_context)); {0, 1, 2, 3, 4, 5, 6, 7}, random_context));
@ -960,10 +946,10 @@ BOOST_AUTO_TEST_CASE(node_eviction_test)
// Combination of all tests above. // Combination of all tests above.
BOOST_CHECK(!IsEvicted( BOOST_CHECK(!IsEvicted(
number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) { number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
candidate.nKeyedNetGroup = number_of_nodes - candidate.id; // 4 protected candidate.nKeyedNetGroup = number_of_nodes - candidate.id; // 4 protected
candidate.m_min_ping_time = candidate.id; // 8 protected candidate.m_min_ping_time = std::chrono::microseconds{candidate.id}; // 8 protected
candidate.nLastTXTime = number_of_nodes - candidate.id; // 4 protected candidate.nLastTXTime = number_of_nodes - candidate.id; // 4 protected
candidate.nLastBlockTime = number_of_nodes - candidate.id; // 4 protected candidate.nLastBlockTime = number_of_nodes - candidate.id; // 4 protected
}, },
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, random_context)); {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, random_context));

View File

@ -31,9 +31,16 @@ void UninterruptibleSleep(const std::chrono::microseconds& n);
* This helper is used to convert durations before passing them over an * This helper is used to convert durations before passing them over an
* interface that doesn't support std::chrono (e.g. RPC, debug log, or the GUI) * interface that doesn't support std::chrono (e.g. RPC, debug log, or the GUI)
*/ */
inline int64_t count_seconds(std::chrono::seconds t) { return t.count(); } constexpr int64_t count_seconds(std::chrono::seconds t) { return t.count(); }
inline int64_t count_milliseconds(std::chrono::milliseconds t) { return t.count(); } constexpr int64_t count_milliseconds(std::chrono::milliseconds t) { return t.count(); }
inline int64_t count_microseconds(std::chrono::microseconds t) { return t.count(); } constexpr int64_t count_microseconds(std::chrono::microseconds t) { return t.count(); }
using SecondsDouble = std::chrono::duration<double, std::chrono::seconds::period>;
/**
* Helper to count the seconds in any std::chrono::duration type
*/
inline double CountSecondsDouble(SecondsDouble t) { return t.count(); }
/** /**
* DEPRECATED * DEPRECATED