diff --git a/src/net.cpp b/src/net.cpp index 399b41f3aa5..7152f62a691 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -664,7 +664,7 @@ bool CNode::ReceiveMsgBytes(std::span msg_bytes, bool& complete) complete = false; const auto time{NodeClock::now()}; LOCK(cs_vRecv); - m_last_recv = std::chrono::duration_cast(time.time_since_epoch()); + m_last_recv = time; nRecvBytes += msg_bytes.size(); while (msg_bytes.size() > 0) { // absorb network data @@ -1643,7 +1643,7 @@ std::pair CConnman::SocketSendData(CNode& node) const nBytes = node.m_sock->Send(data.data(), data.size(), flags); } if (nBytes > 0) { - node.m_last_send = GetTime(); + node.m_last_send = NodeClock::now(); node.nSendBytes += nBytes; // Notify transport that bytes have been processed. node.m_transport->MarkBytesSent(nBytes); @@ -2005,12 +2005,12 @@ void CConnman::NotifyNumConnectionsChanged() } } -bool CConnman::ShouldRunInactivityChecks(const CNode& node, std::chrono::microseconds now) const +bool CConnman::ShouldRunInactivityChecks(const CNode& node, NodeClock::time_point now) const { - return node.m_connected + m_peer_connect_timeout < now; + return node.m_connected + m_peer_connect_timeout < now.time_since_epoch(); } -bool CConnman::InactivityCheck(const CNode& node, std::chrono::microseconds now) const +bool CConnman::InactivityCheck(const CNode& node, NodeClock::time_point now) const { // Tests that see disconnects after using mocktime can start nodes with a // large timeout. For example, -peertimeout=999999999. @@ -2019,8 +2019,8 @@ bool CConnman::InactivityCheck(const CNode& node, std::chrono::microseconds now) if (!ShouldRunInactivityChecks(node, now)) return false; - bool has_received{last_recv.count() != 0}; - bool has_sent{last_send.count() != 0}; + bool has_received{last_recv > NodeClock::epoch}; + bool has_sent{last_send > NodeClock::epoch}; if (!has_received || !has_sent) { std::string has_never; @@ -2127,7 +2127,7 @@ void CConnman::SocketHandlerConnected(const std::vector& nodes, { AssertLockNotHeld(m_total_bytes_sent_mutex); - auto now = GetTime(); + const auto now{NodeClock::now()}; for (CNode* pnode : nodes) { if (m_interrupt_net->interrupted()) { diff --git a/src/net.h b/src/net.h index acef9035c59..4f082b4efde 100644 --- a/src/net.h +++ b/src/net.h @@ -192,8 +192,8 @@ class CNodeStats { public: NodeId nodeid; - std::chrono::seconds m_last_send; - std::chrono::seconds m_last_recv; + NodeClock::time_point m_last_send; + NodeClock::time_point m_last_recv; std::chrono::seconds m_last_tx_time; std::chrono::seconds m_last_block_time; std::chrono::seconds m_connected; @@ -707,8 +707,8 @@ public: uint64_t nRecvBytes GUARDED_BY(cs_vRecv){0}; - std::atomic m_last_send{0s}; - std::atomic m_last_recv{0s}; + std::atomic m_last_send{NodeClock::epoch}; + std::atomic m_last_recv{NodeClock::epoch}; //! Unix epoch time at peer connection const std::chrono::seconds m_connected; // Address of this peer @@ -1396,7 +1396,7 @@ public: void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc); /** Return true if we should disconnect the peer for failing an inactivity check. */ - bool ShouldRunInactivityChecks(const CNode& node, std::chrono::microseconds now) const; + bool ShouldRunInactivityChecks(const CNode& node, NodeClock::time_point now) const; bool MultipleManualOrFullOutboundConns(Network net) const EXCLUSIVE_LOCKS_REQUIRED(m_nodes_mutex); @@ -1447,7 +1447,7 @@ private: void DisconnectNodes() EXCLUSIVE_LOCKS_REQUIRED(!m_reconnections_mutex, !m_nodes_mutex); void NotifyNumConnectionsChanged(); /** Return true if the peer is inactive and should be disconnected. */ - bool InactivityCheck(const CNode& node, std::chrono::microseconds now) const; + bool InactivityCheck(const CNode& node, NodeClock::time_point now) const; /** * Generate a collection of sockets to check for IO readiness. diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 507be59cb7c..6b35242608b 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -275,7 +275,7 @@ struct Peer { /** The pong reply we're expecting, or 0 if no pong expected. */ std::atomic m_ping_nonce_sent{0}; /** When the last ping was sent, or 0 if no ping was ever sent */ - std::atomic m_ping_start{0us}; + std::atomic m_ping_start{NodeClock::epoch}; /** Whether a ping has been requested by the user */ std::atomic m_ping_queued{false}; @@ -732,7 +732,7 @@ private: * May mark the peer to be disconnected if a ping has timed out. * We use mockable time for ping timeouts, so setmocktime may cause pings * to time out. */ - void MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::microseconds now); + void MaybeSendPing(CNode& node_to, Peer& peer, NodeClock::time_point now); /** Send `addr` messages on a regular schedule. */ void MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex); @@ -1809,9 +1809,9 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c // since pingtime does not update until the ping is complete, which might take a while. // So, if a ping is taking an unusually long time in flight, // the caller can immediately detect that this is happening. - auto ping_wait{0us}; - if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) { - ping_wait = GetTime() - peer->m_ping_start.load(); + NodeClock::duration ping_wait{0us}; + if ((0 != peer->m_ping_nonce_sent) && (peer->m_ping_start.load() > NodeClock::epoch)) { + ping_wait = NodeClock::now() - peer->m_ping_start.load(); } if (auto tx_relay = peer->GetTxRelay(); tx_relay != nullptr) { @@ -4158,7 +4158,7 @@ void PeerManagerImpl::ProcessMessage(Peer& peer, CNode& pfrom, const std::string MakeAndPushMessage(pfrom, NetMsgType::TX, TX_WITH_WITNESS(*pushed_tx)); peer.m_ping_queued = true; // Ensure a ping will be sent: mimic a request via RPC. - MaybeSendPing(pfrom, peer, GetTime()); + MaybeSendPing(pfrom, peer, NodeClock::now()); } else { LogDebug(BCLog::PRIVBROADCAST, "Disconnecting: got an unexpected GETDATA message, %s", pfrom.LogPeer()); @@ -4900,7 +4900,7 @@ void PeerManagerImpl::ProcessMessage(Peer& peer, CNode& pfrom, const std::string } if (msg_type == NetMsgType::PONG) { - const auto ping_end{time_received.time_since_epoch()}; + const auto ping_end{time_received}; uint64_t nonce = 0; size_t nAvail = vRecv.in_avail(); bool bPingFinished = false; @@ -5396,7 +5396,7 @@ void PeerManagerImpl::CheckForStaleTipAndEvictPeers() } } -void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::microseconds now) +void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, NodeClock::time_point now) { if (m_connman.ShouldRunInactivityChecks(node_to, now) && peer.m_ping_nonce_sent && @@ -5733,6 +5733,7 @@ bool PeerManagerImpl::SendMessages(CNode& node) if (!node.fSuccessfullyConnected || node.fDisconnect) return true; + const auto now{NodeClock::now()}; const auto current_time{GetTime()}; // The logic below does not apply to private broadcast peers, so skip it. @@ -5753,7 +5754,7 @@ bool PeerManagerImpl::SendMessages(CNode& node) return true; } - MaybeSendPing(node, peer, current_time); + MaybeSendPing(node, peer, now); // MaybeSendPing may have marked peer for disconnection if (node.fDisconnect) return true; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index d30a8acff62..fef1f687208 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1165,12 +1165,13 @@ void RPCConsole::updateDetailWidget() if (stats->nodeStats.m_bip152_highbandwidth_from) bip152_hb_settings += (bip152_hb_settings.isEmpty() ? ts.from : QLatin1Char('/') + ts.from); if (bip152_hb_settings.isEmpty()) bip152_hb_settings = ts.no; ui->peerHighBandwidth->setText(bip152_hb_settings); + const auto now{NodeClock::now()}; const auto time_now{GetTime()}; ui->peerConnTime->setText(GUIUtil::formatDurationStr(time_now - stats->nodeStats.m_connected)); ui->peerLastBlock->setText(TimeDurationField(time_now, stats->nodeStats.m_last_block_time)); ui->peerLastTx->setText(TimeDurationField(time_now, stats->nodeStats.m_last_tx_time)); - ui->peerLastSend->setText(TimeDurationField(time_now, stats->nodeStats.m_last_send)); - ui->peerLastRecv->setText(TimeDurationField(time_now, stats->nodeStats.m_last_recv)); + ui->peerLastSend->setText(TimeDurationField(now, stats->nodeStats.m_last_send)); + ui->peerLastRecv->setText(TimeDurationField(now, stats->nodeStats.m_last_recv)); ui->peerBytesSent->setText(GUIUtil::formatBytes(stats->nodeStats.nSendBytes)); ui->peerBytesRecv->setText(GUIUtil::formatBytes(stats->nodeStats.nRecvBytes)); ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.m_last_ping_time)); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index bbd469cd3dd..0c9f704090b 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -182,7 +182,12 @@ private: /** Update UI with latest network info from model. */ void updateNetworkState(); - /** Helper for the output of a time duration field. Inputs are UNIX epoch times. */ + /// Format the duration between now and event as a string. + QString TimeDurationField(NodeClock::time_point now, NodeClock::time_point event) const + { + return event > NodeClock::epoch ? GUIUtil::formatDurationStr(now - event) : tr("Never"); + } + /// DEPRECATED: Helper for the output of a time duration field. Inputs are UNIX epoch times. QString TimeDurationField(std::chrono::seconds time_now, std::chrono::seconds time_at_event) const { return time_at_event.count() ? GUIUtil::formatDurationStr(time_now - time_at_event) : tr("Never"); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 9c71e4ee8ce..ff2adf82d37 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -242,8 +242,8 @@ static RPCHelpMan getpeerinfo() obj.pushKV("relaytxes", statestats.m_relay_txs); obj.pushKV("last_inv_sequence", statestats.m_last_inv_seq); obj.pushKV("inv_to_send", statestats.m_inv_to_send); - obj.pushKV("lastsend", count_seconds(stats.m_last_send)); - obj.pushKV("lastrecv", count_seconds(stats.m_last_recv)); + obj.pushKV("lastsend", TicksSinceEpoch(stats.m_last_send)); + obj.pushKV("lastrecv", TicksSinceEpoch(stats.m_last_recv)); obj.pushKV("last_transaction", count_seconds(stats.m_last_tx_time)); obj.pushKV("last_block", count_seconds(stats.m_last_block_time)); obj.pushKV("bytessent", stats.nSendBytes);