Skip to content

Commit e460c0a

Browse files
committed
Merge bitcoin/bitcoin#27405: util: Use steady clock instead of system clock to measure durations
fa83fb3 wallet: Use steady clock to calculate number of derive iterations (MarcoFalke) fa2c099 wallet: Use steady clock to measure scanning duration (MarcoFalke) fa97621 qt: Use steady clock to throttle GUI notifications (MarcoFalke) fa1d804 test: Use steady clock in index tests (MarcoFalke) fa454dc net: Use steady clock in InterruptibleRecv (MarcoFalke) Pull request description: `GetTimeMillis` has multiple issues: * It doesn't denote the underlying clock type * It isn't type-safe * It is used incorrectly in places that should use a steady clock Fix all issues here. ACKs for top commit: willcl-ark: ACK fa83fb3 martinus: Code review ACK bitcoin/bitcoin@fa83fb3, also ran all tests. All usages of the steady_clock are just for duration measurements, so the change to a different epoch is ok. Tree-SHA512: 5ec4fede8c7f97e2e08863c011856e8304f16ba30a68fdeb42f96a50a04961092cbe46ccf9ea6ac99ff5203c09f9e0924eb483eb38d7df0759addc85116c8a9f
2 parents 4a72af9 + fa83fb3 commit e460c0a

File tree

8 files changed

+36
-34
lines changed

8 files changed

+36
-34
lines changed

src/netbase.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ static Proxy nameProxy GUARDED_BY(g_proxyinfo_mutex);
3636
int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
3737
bool fNameLookup = DEFAULT_NAME_LOOKUP;
3838

39-
// Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
40-
int g_socks5_recv_timeout = 20 * 1000;
39+
// Need ample time for negotiation for very slow proxies such as Tor
40+
std::chrono::milliseconds g_socks5_recv_timeout = 20s;
4141
static std::atomic<bool> interruptSocks5Recv(false);
4242

4343
std::vector<CNetAddr> WrappedGetAddrInfo(const std::string& name, bool allow_lookup)
@@ -296,7 +296,7 @@ enum class IntrRecvError {
296296
*
297297
* @param data The buffer where the read bytes should be stored.
298298
* @param len The number of bytes to read into the specified buffer.
299-
* @param timeout The total timeout in milliseconds for this read.
299+
* @param timeout The total timeout for this read.
300300
* @param sock The socket (has to be in non-blocking mode) from which to read bytes.
301301
*
302302
* @returns An IntrRecvError indicating the resulting status of this read.
@@ -306,10 +306,10 @@ enum class IntrRecvError {
306306
* @see This function can be interrupted by calling InterruptSocks5(bool).
307307
* Sockets can be made non-blocking with Sock::SetNonBlocking().
308308
*/
309-
static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const Sock& sock)
309+
static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, std::chrono::milliseconds timeout, const Sock& sock)
310310
{
311-
int64_t curTime = GetTimeMillis();
312-
int64_t endTime = curTime + timeout;
311+
auto curTime{Now<SteadyMilliseconds>()};
312+
const auto endTime{curTime + timeout};
313313
while (len > 0 && curTime < endTime) {
314314
ssize_t ret = sock.Recv(data, len, 0); // Optimistically try the recv first
315315
if (ret > 0) {
@@ -333,7 +333,7 @@ static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, c
333333
}
334334
if (interruptSocks5Recv)
335335
return IntrRecvError::Interrupted;
336-
curTime = GetTimeMillis();
336+
curTime = Now<SteadyMilliseconds>();
337337
}
338338
return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
339339
}

src/qt/clientmodel.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
#include <QThread>
2929
#include <QTimer>
3030

31-
static int64_t nLastHeaderTipUpdateNotification = 0;
32-
static int64_t nLastBlockTipUpdateNotification = 0;
31+
static SteadyClock::time_point g_last_header_tip_update_notification{};
32+
static SteadyClock::time_point g_last_block_tip_update_notification{};
3333

3434
ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QObject *parent) :
3535
QObject(parent),
@@ -222,9 +222,9 @@ void ClientModel::TipChanged(SynchronizationState sync_state, interfaces::BlockT
222222

223223
// Throttle GUI notifications about (a) blocks during initial sync, and (b) both blocks and headers during reindex.
224224
const bool throttle = (sync_state != SynchronizationState::POST_INIT && synctype == SyncType::BLOCK_SYNC) || sync_state == SynchronizationState::INIT_REINDEX;
225-
const int64_t now = throttle ? GetTimeMillis() : 0;
226-
int64_t& nLastUpdateNotification = synctype != SyncType::BLOCK_SYNC ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
227-
if (throttle && now < nLastUpdateNotification + count_milliseconds(MODEL_UPDATE_DELAY)) {
225+
const auto now{throttle ? SteadyClock::now() : SteadyClock::time_point{}};
226+
auto& nLastUpdateNotification = synctype != SyncType::BLOCK_SYNC ? g_last_header_tip_update_notification : g_last_block_tip_update_notification;
227+
if (throttle && now < nLastUpdateNotification + MODEL_UPDATE_DELAY) {
228228
return;
229229
}
230230

src/test/blockfilter_index_tests.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,10 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
141141
BOOST_REQUIRE(filter_index.Start());
142142

143143
// Allow filter index to catch up with the block index.
144-
constexpr int64_t timeout_ms = 10 * 1000;
145-
int64_t time_start = GetTimeMillis();
144+
constexpr auto timeout{10s};
145+
const auto time_start{SteadyClock::now()};
146146
while (!filter_index.BlockUntilSyncedToCurrentChain()) {
147-
BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
147+
BOOST_REQUIRE(time_start + timeout > SteadyClock::now());
148148
UninterruptibleSleep(std::chrono::milliseconds{100});
149149
}
150150

src/test/fuzz/socks5.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
#include <string>
1515
#include <vector>
1616

17+
extern std::chrono::milliseconds g_socks5_recv_timeout;
18+
1719
namespace {
18-
int default_socks5_recv_timeout;
20+
decltype(g_socks5_recv_timeout) default_socks5_recv_timeout;
1921
};
2022

21-
extern int g_socks5_recv_timeout;
22-
2323
void initialize_socks5()
2424
{
2525
static const auto testing_setup = MakeNoLogFileContext<const BasicTestingSetup>();
@@ -35,7 +35,7 @@ FUZZ_TARGET_INIT(socks5, initialize_socks5)
3535
InterruptSocks5(fuzzed_data_provider.ConsumeBool());
3636
// Set FUZZED_SOCKET_FAKE_LATENCY=1 to exercise recv timeout code paths. This
3737
// will slow down fuzzing.
38-
g_socks5_recv_timeout = (fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) ? 1 : default_socks5_recv_timeout;
38+
g_socks5_recv_timeout = (fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) ? 1ms : default_socks5_recv_timeout;
3939
FuzzedSock fuzzed_sock = ConsumeSock(fuzzed_data_provider);
4040
// This Socks5(...) fuzzing harness would have caught CVE-2017-18350 within
4141
// a few seconds of fuzzing.

src/test/txindex_tests.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
3232
BOOST_REQUIRE(txindex.Start());
3333

3434
// Allow tx index to catch up with the block index.
35-
constexpr int64_t timeout_ms = 10 * 1000;
36-
int64_t time_start = GetTimeMillis();
35+
constexpr auto timeout{10s};
36+
const auto time_start{SteadyClock::now()};
3737
while (!txindex.BlockUntilSyncedToCurrentChain()) {
38-
BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
38+
BOOST_REQUIRE(time_start + timeout > SteadyClock::now());
3939
UninterruptibleSleep(std::chrono::milliseconds{100});
4040
}
4141

src/wallet/rpc/wallet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ static RPCHelpMan getwalletinfo()
122122
obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
123123
if (pwallet->IsScanning()) {
124124
UniValue scanning(UniValue::VOBJ);
125-
scanning.pushKV("duration", pwallet->ScanningDuration() / 1000);
125+
scanning.pushKV("duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
126126
scanning.pushKV("progress", pwallet->ScanningProgress());
127127
obj.pushKV("scanning", scanning);
128128
} else {

src/wallet/wallet.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -559,13 +559,14 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
559559
return false;
560560
if (Unlock(_vMasterKey))
561561
{
562-
int64_t nStartTime = GetTimeMillis();
562+
constexpr MillisecondsDouble target{100};
563+
auto start{SteadyClock::now()};
563564
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
564-
pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))));
565+
pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
565566

566-
nStartTime = GetTimeMillis();
567+
start = SteadyClock::now();
567568
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
568-
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
569+
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
569570

570571
if (pMasterKey.second.nDeriveIterations < 25000)
571572
pMasterKey.second.nDeriveIterations = 25000;
@@ -762,13 +763,14 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
762763
GetStrongRandBytes(kMasterKey.vchSalt);
763764

764765
CCrypter crypter;
765-
int64_t nStartTime = GetTimeMillis();
766+
constexpr MillisecondsDouble target{100};
767+
auto start{SteadyClock::now()};
766768
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
767-
kMasterKey.nDeriveIterations = static_cast<unsigned int>(2500000 / ((double)(GetTimeMillis() - nStartTime)));
769+
kMasterKey.nDeriveIterations = static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
768770

769-
nStartTime = GetTimeMillis();
771+
start = SteadyClock::now();
770772
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
771-
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
773+
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
772774

773775
if (kMasterKey.nDeriveIterations < 25000)
774776
kMasterKey.nDeriveIterations = 25000;

src/wallet/wallet.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
284284
std::atomic<bool> fScanningWallet{false}; // controlled by WalletRescanReserver
285285
std::atomic<bool> m_attaching_chain{false};
286286
std::atomic<bool> m_scanning_with_passphrase{false};
287-
std::atomic<int64_t> m_scanning_start{0};
287+
std::atomic<SteadyClock::time_point> m_scanning_start{SteadyClock::time_point{}};
288288
std::atomic<double> m_scanning_progress{0};
289289
friend class WalletRescanReserver;
290290

@@ -505,7 +505,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
505505
bool IsAbortingRescan() const { return fAbortRescan; }
506506
bool IsScanning() const { return fScanningWallet; }
507507
bool IsScanningWithPassphrase() const { return m_scanning_with_passphrase; }
508-
int64_t ScanningDuration() const { return fScanningWallet ? GetTimeMillis() - m_scanning_start : 0; }
508+
SteadyClock::duration ScanningDuration() const { return fScanningWallet ? SteadyClock::now() - m_scanning_start.load() : SteadyClock::duration{}; }
509509
double ScanningProgress() const { return fScanningWallet ? (double) m_scanning_progress : 0; }
510510

511511
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
@@ -1014,7 +1014,7 @@ class WalletRescanReserver
10141014
return false;
10151015
}
10161016
m_wallet.m_scanning_with_passphrase.exchange(with_passphrase);
1017-
m_wallet.m_scanning_start = GetTimeMillis();
1017+
m_wallet.m_scanning_start = SteadyClock::now();
10181018
m_wallet.m_scanning_progress = 0;
10191019
m_could_reserve = true;
10201020
return true;

0 commit comments

Comments
 (0)