diff options
-rw-r--r-- | src/net.cpp | 3 | ||||
-rw-r--r-- | src/net_processing.cpp | 6 | ||||
-rw-r--r-- | src/random.h | 33 | ||||
-rw-r--r-- | src/test/random_tests.cpp | 24 |
4 files changed, 36 insertions, 30 deletions
diff --git a/src/net.cpp b/src/net.cpp index ac66540022..9e969718b7 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3475,7 +3475,8 @@ std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addres // nodes to be "terrible" (see IsTerrible()) if the timestamps are older than 30 days, // max. 24 hours of "penalty" due to cache shouldn't make any meaningful difference // in terms of the freshness of the response. - cache_entry.m_cache_entry_expiration = current_time + std::chrono::hours(21) + GetRandMicros(std::chrono::hours(6)); + cache_entry.m_cache_entry_expiration = current_time + + 21h + FastRandomContext().randrange<std::chrono::microseconds>(6h); } return cache_entry.m_addrs_response_cache; } diff --git a/src/net_processing.cpp b/src/net_processing.cpp index d674811ba7..ce3ff71df1 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1698,7 +1698,7 @@ void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler) // Schedule next run for 10-15 minutes in the future. // We add randomness on every cycle to avoid the possibility of P2P fingerprinting. - const std::chrono::milliseconds delta = 10min + GetRandMillis(5min); + const auto delta = 10min + FastRandomContext().randrange<std::chrono::milliseconds>(5min); scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta); } @@ -2050,7 +2050,7 @@ void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler) scheduler.scheduleEvery([this] { this->CheckForStaleTipAndEvictPeers(); }, std::chrono::seconds{EXTRA_PEER_CHECK_INTERVAL}); // schedule next run for 10-15 minutes in the future - const std::chrono::milliseconds delta = 10min + GetRandMillis(5min); + const auto delta = 10min + FastRandomContext().randrange<std::chrono::milliseconds>(5min); scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta); } @@ -5753,7 +5753,7 @@ void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::mi // until scheduled broadcast, then move the broadcast to within MAX_FEEFILTER_CHANGE_DELAY. else if (current_time + MAX_FEEFILTER_CHANGE_DELAY < peer.m_next_send_feefilter && (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) { - peer.m_next_send_feefilter = current_time + GetRandomDuration<std::chrono::microseconds>(MAX_FEEFILTER_CHANGE_DELAY); + peer.m_next_send_feefilter = current_time + FastRandomContext().randrange<std::chrono::microseconds>(MAX_FEEFILTER_CHANGE_DELAY); } } diff --git a/src/random.h b/src/random.h index 1573e49ef7..b9cba1d602 100644 --- a/src/random.h +++ b/src/random.h @@ -132,6 +132,13 @@ concept RandomNumberGenerator = requires(T& rng, Span<std::byte> s) { requires std::derived_from<std::remove_reference_t<T>, RandomMixin<std::remove_reference_t<T>>>; }; +/** A concept for C++ std::chrono durations. */ +template<typename T> +concept StdChronoDuration = requires { + []<class Rep, class Period>(std::type_identity<std::chrono::duration<Rep, Period>>){}( + std::type_identity<T>()); +}; + /** Mixin class that provides helper randomness functions. * * Intended to be used through CRTP: https://en.cppreference.com/w/cpp/language/crtp. @@ -300,7 +307,7 @@ public: } /** Generate a uniform random duration in the range from 0 (inclusive) to range (exclusive). */ - template <typename Chrono> + template <typename Chrono> requires StdChronoDuration<typename Chrono::duration> typename Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept { using Dur = typename Chrono::duration; @@ -309,6 +316,17 @@ public: /* interval [0..0] */ Dur{0}; }; + /** Generate a uniform random duration in the range [0..max). Precondition: max.count() > 0 */ + template <StdChronoDuration Dur> + Dur randrange(typename std::common_type_t<Dur> range) noexcept + // Having the compiler infer the template argument from the function argument + // is dangerous, because the desired return value generally has a different + // type than the function argument. So std::common_type is used to force the + // call site to specify the type of the return value. + { + return Dur{Impl().randrange(range.count())}; + } + // Compatibility with the UniformRandomBitGenerator concept typedef uint64_t result_type; static constexpr uint64_t min() noexcept { return 0; } @@ -426,19 +444,6 @@ void Shuffle(I first, I last, R&& rng) } } -/** Generate a uniform random duration in the range [0..max). Precondition: max.count() > 0 */ -template <typename D> -D GetRandomDuration(typename std::common_type<D>::type max) noexcept -// Having the compiler infer the template argument from the function argument -// is dangerous, because the desired return value generally has a different -// type than the function argument. So std::common_type is used to force the -// call site to specify the type of the return value. -{ - return D{FastRandomContext().randrange(max.count())}; -}; -constexpr auto GetRandMicros = GetRandomDuration<std::chrono::microseconds>; -constexpr auto GetRandMillis = GetRandomDuration<std::chrono::milliseconds>; - /* Number of random bytes returned by GetOSRand. * When changing this constant make sure to change all call sites, and make * sure that the underlying OS APIs for all platforms support the number. diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 6932e186d5..b7479d310c 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -30,18 +30,18 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests_deterministic) { BOOST_CHECK_EQUAL(FastRandomContext().rand<uint64_t>(), uint64_t{9330418229102544152u}); BOOST_CHECK_EQUAL(FastRandomContext().rand<int>(), int{618925161}); - BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 1271170921); - BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 2803534); + BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::microseconds>(1h).count(), 1271170921); + BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count(), 2803534); BOOST_CHECK_EQUAL(FastRandomContext().rand<uint64_t>(), uint64_t{10170981140880778086u}); BOOST_CHECK_EQUAL(FastRandomContext().rand<int>(), int{1689082725}); - BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 2464643716); - BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 2312205); + BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::microseconds>(1h).count(), 2464643716); + BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count(), 2312205); BOOST_CHECK_EQUAL(FastRandomContext().rand<uint64_t>(), uint64_t{5689404004456455543u}); BOOST_CHECK_EQUAL(FastRandomContext().rand<int>(), int{785839937}); - BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 93558804); - BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 507022); + BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::microseconds>(1h).count(), 93558804); + BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count(), 507022); } { @@ -84,18 +84,18 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests_nondeterministic) { BOOST_CHECK(FastRandomContext().rand<uint64_t>() != uint64_t{9330418229102544152u}); BOOST_CHECK(FastRandomContext().rand<int>() != int{618925161}); - BOOST_CHECK(GetRandMicros(std::chrono::hours{1}).count() != 1271170921); - BOOST_CHECK(GetRandMillis(std::chrono::hours{1}).count() != 2803534); + BOOST_CHECK(FastRandomContext().randrange<std::chrono::microseconds>(1h).count() != 1271170921); + BOOST_CHECK(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count() != 2803534); BOOST_CHECK(FastRandomContext().rand<uint64_t>() != uint64_t{10170981140880778086u}); BOOST_CHECK(FastRandomContext().rand<int>() != int{1689082725}); - BOOST_CHECK(GetRandMicros(std::chrono::hours{1}).count() != 2464643716); - BOOST_CHECK(GetRandMillis(std::chrono::hours{1}).count() != 2312205); + BOOST_CHECK(FastRandomContext().randrange<std::chrono::microseconds>(1h).count() != 2464643716); + BOOST_CHECK(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count() != 2312205); BOOST_CHECK(FastRandomContext().rand<uint64_t>() != uint64_t{5689404004456455543u}); BOOST_CHECK(FastRandomContext().rand<int>() != int{785839937}); - BOOST_CHECK(GetRandMicros(std::chrono::hours{1}).count() != 93558804); - BOOST_CHECK(GetRandMillis(std::chrono::hours{1}).count() != 507022); + BOOST_CHECK(FastRandomContext().randrange<std::chrono::microseconds>(1h).count() != 93558804); + BOOST_CHECK(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count() != 507022); } { |