mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 02:33:24 -03:00
Merge bitcoin/bitcoin#27189: util: Use steady clock in SeedStrengthen, FindBestImplementation, FlushStateToDisk
fa1b4e5c32
Use steady clock in FlushStateToDisk (MarcoFalke)1111e2f8b4
Use steady clock in SeedStrengthen and FindBestImplementation (MarcoFalke) Pull request description: There may be a theoretical deadlock for the duration of the offset when the system clock is adjusted into a past time while executing `SeedStrengthen`. Fix this by using steady clock. Do the same in `FindBestImplementation`, which shouldn't be affected, because it discards outlier measurements. However, doing the same there for consistency seems fine. Do the same in `FlushStateToDisk`, which should make the flushes more steady, if the system clock is adjusted by a large offset. ACKs for top commit: john-moffett: ACKfa1b4e5c32
willcl-ark: ACKfa1b4e5c3
Tree-SHA512: cc625e796b186accd53222bd64eb57d0512bc7e588312d254349b542bbc5e5daac348ff2b3b3f7dc5ae0bbbae2ec11fdbf3022cf2164211633765a4b0108e83e
This commit is contained in:
commit
2de0559f2c
6 changed files with 20 additions and 18 deletions
|
@ -51,12 +51,14 @@ if [ "${RUN_TIDY}" = "true" ]; then
|
|||
" src/node/chainstate.cpp"\
|
||||
" src/node/chainstatemanager_args.cpp"\
|
||||
" src/node/mempool_args.cpp"\
|
||||
" src/node/minisketchwrapper.cpp"\
|
||||
" src/node/utxo_snapshot.cpp"\
|
||||
" src/node/validation_cache_args.cpp"\
|
||||
" src/policy/feerate.cpp"\
|
||||
" src/policy/packages.cpp"\
|
||||
" src/policy/settings.cpp"\
|
||||
" src/primitives/transaction.cpp"\
|
||||
" src/random.cpp"\
|
||||
" src/rpc/fees.cpp"\
|
||||
" src/rpc/signmessage.cpp"\
|
||||
" src/test/fuzz/txorphan.cpp"\
|
||||
|
|
|
@ -23,17 +23,17 @@ static constexpr uint32_t BITS = 32;
|
|||
|
||||
uint32_t FindBestImplementation()
|
||||
{
|
||||
std::optional<std::pair<int64_t, uint32_t>> best;
|
||||
std::optional<std::pair<SteadyClock::duration, uint32_t>> best;
|
||||
|
||||
uint32_t max_impl = Minisketch::MaxImplementation();
|
||||
for (uint32_t impl = 0; impl <= max_impl; ++impl) {
|
||||
std::vector<int64_t> benches;
|
||||
std::vector<SteadyClock::duration> benches;
|
||||
uint64_t offset = 0;
|
||||
/* Run a little benchmark with capacity 32, adding 184 entries, and decoding 11 of them once. */
|
||||
for (int b = 0; b < 11; ++b) {
|
||||
if (!Minisketch::ImplementationSupported(BITS, impl)) break;
|
||||
Minisketch sketch(BITS, impl, 32);
|
||||
auto start = GetTimeMicros();
|
||||
auto start = SteadyClock::now();
|
||||
for (uint64_t e = 0; e < 100; ++e) {
|
||||
sketch.Add(e*1337 + b*13337 + offset);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ uint32_t FindBestImplementation()
|
|||
sketch.Add(e*1337 + b*13337 + offset);
|
||||
}
|
||||
offset += (*sketch.Decode(32))[0];
|
||||
auto stop = GetTimeMicros();
|
||||
auto stop = SteadyClock::now();
|
||||
benches.push_back(stop - start);
|
||||
}
|
||||
/* Remember which implementation has the best median benchmark time. */
|
||||
|
|
|
@ -221,14 +221,14 @@ static void SeedHardwareSlow(CSHA512& hasher) noexcept {
|
|||
}
|
||||
|
||||
/** Use repeated SHA512 to strengthen the randomness in seed32, and feed into hasher. */
|
||||
static void Strengthen(const unsigned char (&seed)[32], int microseconds, CSHA512& hasher) noexcept
|
||||
static void Strengthen(const unsigned char (&seed)[32], SteadyClock::duration dur, CSHA512& hasher) noexcept
|
||||
{
|
||||
CSHA512 inner_hasher;
|
||||
inner_hasher.Write(seed, sizeof(seed));
|
||||
|
||||
// Hash loop
|
||||
unsigned char buffer[64];
|
||||
int64_t stop = GetTimeMicros() + microseconds;
|
||||
const auto stop{SteadyClock::now() + dur};
|
||||
do {
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
inner_hasher.Finalize(buffer);
|
||||
|
@ -238,7 +238,7 @@ static void Strengthen(const unsigned char (&seed)[32], int microseconds, CSHA51
|
|||
// Benchmark operation and feed it into outer hasher.
|
||||
int64_t perf = GetPerformanceCounter();
|
||||
hasher.Write((const unsigned char*)&perf, sizeof(perf));
|
||||
} while (GetTimeMicros() < stop);
|
||||
} while (SteadyClock::now() < stop);
|
||||
|
||||
// Produce output from inner state and feed it to outer hasher.
|
||||
inner_hasher.Finalize(buffer);
|
||||
|
@ -492,13 +492,13 @@ static void SeedSlow(CSHA512& hasher, RNGState& rng) noexcept
|
|||
}
|
||||
|
||||
/** Extract entropy from rng, strengthen it, and feed it into hasher. */
|
||||
static void SeedStrengthen(CSHA512& hasher, RNGState& rng, int microseconds) noexcept
|
||||
static void SeedStrengthen(CSHA512& hasher, RNGState& rng, SteadyClock::duration dur) noexcept
|
||||
{
|
||||
// Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.
|
||||
unsigned char strengthen_seed[32];
|
||||
rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
|
||||
// Strengthen the seed, and feed it into hasher.
|
||||
Strengthen(strengthen_seed, microseconds, hasher);
|
||||
Strengthen(strengthen_seed, dur, hasher);
|
||||
}
|
||||
|
||||
static void SeedPeriodic(CSHA512& hasher, RNGState& rng) noexcept
|
||||
|
@ -518,7 +518,7 @@ static void SeedPeriodic(CSHA512& hasher, RNGState& rng) noexcept
|
|||
LogPrint(BCLog::RAND, "Feeding %i bytes of dynamic environment data into RNG\n", hasher.Size() - old_size);
|
||||
|
||||
// Strengthen for 10 ms
|
||||
SeedStrengthen(hasher, rng, 10000);
|
||||
SeedStrengthen(hasher, rng, 10ms);
|
||||
}
|
||||
|
||||
static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
|
||||
|
@ -538,7 +538,7 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
|
|||
LogPrint(BCLog::RAND, "Feeding %i bytes of environment data into RNG\n", hasher.Size() - old_size);
|
||||
|
||||
// Strengthen for 100 ms
|
||||
SeedStrengthen(hasher, rng, 100000);
|
||||
SeedStrengthen(hasher, rng, 100ms);
|
||||
}
|
||||
|
||||
enum class RNGLevel {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <compat/compat.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <chrono> // IWYU pragma: export
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
|
|
|
@ -2478,12 +2478,12 @@ bool Chainstate::FlushStateToDisk(
|
|||
}
|
||||
}
|
||||
}
|
||||
const auto nNow = GetTime<std::chrono::microseconds>();
|
||||
const auto nNow{SteadyClock::now()};
|
||||
// Avoid writing/flushing immediately after startup.
|
||||
if (m_last_write.count() == 0) {
|
||||
if (m_last_write == decltype(m_last_write){}) {
|
||||
m_last_write = nNow;
|
||||
}
|
||||
if (m_last_flush.count() == 0) {
|
||||
if (m_last_flush == decltype(m_last_flush){}) {
|
||||
m_last_flush = nNow;
|
||||
}
|
||||
// The cache is large and we're within 10% and 10 MiB of the limit, but we have time now (not in the middle of a block processing).
|
||||
|
@ -2544,7 +2544,7 @@ bool Chainstate::FlushStateToDisk(
|
|||
m_last_flush = nNow;
|
||||
full_flush_completed = true;
|
||||
TRACE5(utxocache, flush,
|
||||
(int64_t)(GetTimeMicros() - nNow.count()), // in microseconds (µs)
|
||||
int64_t{Ticks<std::chrono::microseconds>(SteadyClock::now() - nNow)},
|
||||
(uint32_t)mode,
|
||||
(uint64_t)coins_count,
|
||||
(uint64_t)coins_mem_usage,
|
||||
|
|
|
@ -808,8 +808,8 @@ private:
|
|||
void UpdateTip(const CBlockIndex* pindexNew)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||
|
||||
std::chrono::microseconds m_last_write{0};
|
||||
std::chrono::microseconds m_last_flush{0};
|
||||
SteadyClock::time_point m_last_write{};
|
||||
SteadyClock::time_point m_last_flush{};
|
||||
|
||||
/**
|
||||
* In case of an invalid snapshot, rename the coins leveldb directory so
|
||||
|
|
Loading…
Add table
Reference in a new issue