diff --git a/src/net.h b/src/net.h --- a/src/net.h +++ b/src/net.h @@ -877,7 +877,7 @@ // Last time a "MEMPOOL" request was serviced. std::atomic m_last_mempool_req{ std::chrono::seconds{0}}; - int64_t nNextInvSend{0}; + std::chrono::microseconds nNextInvSend{0}; RecursiveMutex cs_feeFilter; // Minimum fee rate with which to filter inv's to this node @@ -1047,6 +1047,15 @@ */ 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::string getSubVersionEB(uint64_t MaxBlockSize); std::string userAgent(const Config &config); + #endif // BITCOIN_NET_H diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -4340,6 +4340,8 @@ // Address refresh broadcast int64_t nNow = GetTimeMicros(); + auto current_time = GetTime(); + if (pto->IsAddrRelayPeer() && !::ChainstateActive().IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) { @@ -4605,17 +4607,18 @@ LOCK(pto->m_tx_relay->cs_tx_inventory); // Check whether periodic sends should happen bool fSendTrickle = pto->HasPermission(PF_NOBAN); - if (pto->m_tx_relay->nNextInvSend < nNow) { + if (pto->m_tx_relay->nNextInvSend < current_time) { fSendTrickle = true; if (pto->fInbound) { - pto->m_tx_relay->nNextInvSend = + pto->m_tx_relay->nNextInvSend = std::chrono::microseconds{ connman->PoissonNextSendInbound( - nNow, INVENTORY_BROADCAST_INTERVAL); + nNow, INVENTORY_BROADCAST_INTERVAL)}; } else { // Use half the delay for outbound peers, as there is less // privacy concern for them. pto->m_tx_relay->nNextInvSend = PoissonNextSend( - nNow, INVENTORY_BROADCAST_INTERVAL >> 1); + current_time, std::chrono::seconds{ + INVENTORY_BROADCAST_INTERVAL >> 1}); } } @@ -4760,7 +4763,7 @@ } // Detect whether we're stalling - const auto current_time = GetTime(); + current_time = GetTime(); // nNow is the current system time (GetTimeMicros is not mockable) and // should be replaced by the mockable current_time eventually nNow = GetTimeMicros(); diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -338,4 +338,20 @@ BOOST_CHECK(1); } +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_SUITE_END()