Skip to content

Commit 4eaa239

Browse files
committed
random: convert GetRand{Micros,Millis} into randrange
There are only a few call sites of these throughout the codebase, so move the functionality into FastRandomContext, and rewrite all call sites. This requires the callers to explicit construct FastRandomContext objects, which do add to the verbosity, but also make potentially apparent locations where the code can be improved by reusing a FastRandomContext object (see further commit).
1 parent 82de1b8 commit 4eaa239

File tree

4 files changed

+36
-30
lines changed

4 files changed

+36
-30
lines changed

src/net.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3475,7 +3475,8 @@ std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addres
34753475
// nodes to be "terrible" (see IsTerrible()) if the timestamps are older than 30 days,
34763476
// max. 24 hours of "penalty" due to cache shouldn't make any meaningful difference
34773477
// in terms of the freshness of the response.
3478-
cache_entry.m_cache_entry_expiration = current_time + std::chrono::hours(21) + GetRandMicros(std::chrono::hours(6));
3478+
cache_entry.m_cache_entry_expiration = current_time +
3479+
21h + FastRandomContext().randrange<std::chrono::microseconds>(6h);
34793480
}
34803481
return cache_entry.m_addrs_response_cache;
34813482
}

src/net_processing.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,7 +1698,7 @@ void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler)
16981698

16991699
// Schedule next run for 10-15 minutes in the future.
17001700
// We add randomness on every cycle to avoid the possibility of P2P fingerprinting.
1701-
const std::chrono::milliseconds delta = 10min + GetRandMillis(5min);
1701+
const auto delta = 10min + FastRandomContext().randrange<std::chrono::milliseconds>(5min);
17021702
scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
17031703
}
17041704

@@ -2050,7 +2050,7 @@ void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler)
20502050
scheduler.scheduleEvery([this] { this->CheckForStaleTipAndEvictPeers(); }, std::chrono::seconds{EXTRA_PEER_CHECK_INTERVAL});
20512051

20522052
// schedule next run for 10-15 minutes in the future
2053-
const std::chrono::milliseconds delta = 10min + GetRandMillis(5min);
2053+
const auto delta = 10min + FastRandomContext().randrange<std::chrono::milliseconds>(5min);
20542054
scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
20552055
}
20562056

@@ -5753,7 +5753,7 @@ void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::mi
57535753
// until scheduled broadcast, then move the broadcast to within MAX_FEEFILTER_CHANGE_DELAY.
57545754
else if (current_time + MAX_FEEFILTER_CHANGE_DELAY < peer.m_next_send_feefilter &&
57555755
(currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5756-
peer.m_next_send_feefilter = current_time + GetRandomDuration<std::chrono::microseconds>(MAX_FEEFILTER_CHANGE_DELAY);
5756+
peer.m_next_send_feefilter = current_time + FastRandomContext().randrange<std::chrono::microseconds>(MAX_FEEFILTER_CHANGE_DELAY);
57575757
}
57585758
}
57595759

src/random.h

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,13 @@ concept RandomNumberGenerator = requires(T& rng, Span<std::byte> s) {
132132
requires std::derived_from<std::remove_reference_t<T>, RandomMixin<std::remove_reference_t<T>>>;
133133
};
134134

135+
/** A concept for C++ std::chrono durations. */
136+
template<typename T>
137+
concept StdChronoDuration = requires {
138+
[]<class Rep, class Period>(std::type_identity<std::chrono::duration<Rep, Period>>){}(
139+
std::type_identity<T>());
140+
};
141+
135142
/** Mixin class that provides helper randomness functions.
136143
*
137144
* Intended to be used through CRTP: https://en.cppreference.com/w/cpp/language/crtp.
@@ -300,7 +307,7 @@ class RandomMixin
300307
}
301308

302309
/** Generate a uniform random duration in the range from 0 (inclusive) to range (exclusive). */
303-
template <typename Chrono>
310+
template <typename Chrono> requires StdChronoDuration<typename Chrono::duration>
304311
typename Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept
305312
{
306313
using Dur = typename Chrono::duration;
@@ -309,6 +316,17 @@ class RandomMixin
309316
/* interval [0..0] */ Dur{0};
310317
};
311318

319+
/** Generate a uniform random duration in the range [0..max). Precondition: max.count() > 0 */
320+
template <StdChronoDuration Dur>
321+
Dur randrange(typename std::common_type_t<Dur> range) noexcept
322+
// Having the compiler infer the template argument from the function argument
323+
// is dangerous, because the desired return value generally has a different
324+
// type than the function argument. So std::common_type is used to force the
325+
// call site to specify the type of the return value.
326+
{
327+
return Dur{Impl().randrange(range.count())};
328+
}
329+
312330
// Compatibility with the UniformRandomBitGenerator concept
313331
typedef uint64_t result_type;
314332
static constexpr uint64_t min() noexcept { return 0; }
@@ -426,19 +444,6 @@ void Shuffle(I first, I last, R&& rng)
426444
}
427445
}
428446

429-
/** Generate a uniform random duration in the range [0..max). Precondition: max.count() > 0 */
430-
template <typename D>
431-
D GetRandomDuration(typename std::common_type<D>::type max) noexcept
432-
// Having the compiler infer the template argument from the function argument
433-
// is dangerous, because the desired return value generally has a different
434-
// type than the function argument. So std::common_type is used to force the
435-
// call site to specify the type of the return value.
436-
{
437-
return D{FastRandomContext().randrange(max.count())};
438-
};
439-
constexpr auto GetRandMicros = GetRandomDuration<std::chrono::microseconds>;
440-
constexpr auto GetRandMillis = GetRandomDuration<std::chrono::milliseconds>;
441-
442447
/* Number of random bytes returned by GetOSRand.
443448
* When changing this constant make sure to change all call sites, and make
444449
* sure that the underlying OS APIs for all platforms support the number.

src/test/random_tests.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,18 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests_deterministic)
3030
{
3131
BOOST_CHECK_EQUAL(FastRandomContext().rand<uint64_t>(), uint64_t{9330418229102544152u});
3232
BOOST_CHECK_EQUAL(FastRandomContext().rand<int>(), int{618925161});
33-
BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 1271170921);
34-
BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 2803534);
33+
BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::microseconds>(1h).count(), 1271170921);
34+
BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count(), 2803534);
3535

3636
BOOST_CHECK_EQUAL(FastRandomContext().rand<uint64_t>(), uint64_t{10170981140880778086u});
3737
BOOST_CHECK_EQUAL(FastRandomContext().rand<int>(), int{1689082725});
38-
BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 2464643716);
39-
BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 2312205);
38+
BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::microseconds>(1h).count(), 2464643716);
39+
BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count(), 2312205);
4040

4141
BOOST_CHECK_EQUAL(FastRandomContext().rand<uint64_t>(), uint64_t{5689404004456455543u});
4242
BOOST_CHECK_EQUAL(FastRandomContext().rand<int>(), int{785839937});
43-
BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 93558804);
44-
BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 507022);
43+
BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::microseconds>(1h).count(), 93558804);
44+
BOOST_CHECK_EQUAL(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count(), 507022);
4545
}
4646

4747
{
@@ -84,18 +84,18 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests_nondeterministic)
8484
{
8585
BOOST_CHECK(FastRandomContext().rand<uint64_t>() != uint64_t{9330418229102544152u});
8686
BOOST_CHECK(FastRandomContext().rand<int>() != int{618925161});
87-
BOOST_CHECK(GetRandMicros(std::chrono::hours{1}).count() != 1271170921);
88-
BOOST_CHECK(GetRandMillis(std::chrono::hours{1}).count() != 2803534);
87+
BOOST_CHECK(FastRandomContext().randrange<std::chrono::microseconds>(1h).count() != 1271170921);
88+
BOOST_CHECK(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count() != 2803534);
8989

9090
BOOST_CHECK(FastRandomContext().rand<uint64_t>() != uint64_t{10170981140880778086u});
9191
BOOST_CHECK(FastRandomContext().rand<int>() != int{1689082725});
92-
BOOST_CHECK(GetRandMicros(std::chrono::hours{1}).count() != 2464643716);
93-
BOOST_CHECK(GetRandMillis(std::chrono::hours{1}).count() != 2312205);
92+
BOOST_CHECK(FastRandomContext().randrange<std::chrono::microseconds>(1h).count() != 2464643716);
93+
BOOST_CHECK(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count() != 2312205);
9494

9595
BOOST_CHECK(FastRandomContext().rand<uint64_t>() != uint64_t{5689404004456455543u});
9696
BOOST_CHECK(FastRandomContext().rand<int>() != int{785839937});
97-
BOOST_CHECK(GetRandMicros(std::chrono::hours{1}).count() != 93558804);
98-
BOOST_CHECK(GetRandMillis(std::chrono::hours{1}).count() != 507022);
97+
BOOST_CHECK(FastRandomContext().randrange<std::chrono::microseconds>(1h).count() != 93558804);
98+
BOOST_CHECK(FastRandomContext().randrange<std::chrono::milliseconds>(1h).count() != 507022);
9999
}
100100

101101
{

0 commit comments

Comments
 (0)