mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
Merge bitcoin/bitcoin#27405: util: Use steady clock instead of system clock to measure durations
fa83fb3161
wallet: Use steady clock to calculate number of derive iterations (MarcoFalke)fa2c099cec
wallet: Use steady clock to measure scanning duration (MarcoFalke)fa97621804
qt: Use steady clock to throttle GUI notifications (MarcoFalke)fa1d8044ab
test: Use steady clock in index tests (MarcoFalke)fa454dcb20
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: ACKfa83fb3161
martinus: Code review ACKfa83fb3161
, 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
This commit is contained in:
commit
e460c0a24a
@ -36,8 +36,8 @@ static Proxy nameProxy GUARDED_BY(g_proxyinfo_mutex);
|
||||
int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
||||
bool fNameLookup = DEFAULT_NAME_LOOKUP;
|
||||
|
||||
// Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
|
||||
int g_socks5_recv_timeout = 20 * 1000;
|
||||
// Need ample time for negotiation for very slow proxies such as Tor
|
||||
std::chrono::milliseconds g_socks5_recv_timeout = 20s;
|
||||
static std::atomic<bool> interruptSocks5Recv(false);
|
||||
|
||||
std::vector<CNetAddr> WrappedGetAddrInfo(const std::string& name, bool allow_lookup)
|
||||
@ -296,7 +296,7 @@ enum class IntrRecvError {
|
||||
*
|
||||
* @param data The buffer where the read bytes should be stored.
|
||||
* @param len The number of bytes to read into the specified buffer.
|
||||
* @param timeout The total timeout in milliseconds for this read.
|
||||
* @param timeout The total timeout for this read.
|
||||
* @param sock The socket (has to be in non-blocking mode) from which to read bytes.
|
||||
*
|
||||
* @returns An IntrRecvError indicating the resulting status of this read.
|
||||
@ -306,10 +306,10 @@ enum class IntrRecvError {
|
||||
* @see This function can be interrupted by calling InterruptSocks5(bool).
|
||||
* Sockets can be made non-blocking with Sock::SetNonBlocking().
|
||||
*/
|
||||
static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const Sock& sock)
|
||||
static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, std::chrono::milliseconds timeout, const Sock& sock)
|
||||
{
|
||||
int64_t curTime = GetTimeMillis();
|
||||
int64_t endTime = curTime + timeout;
|
||||
auto curTime{Now<SteadyMilliseconds>()};
|
||||
const auto endTime{curTime + timeout};
|
||||
while (len > 0 && curTime < endTime) {
|
||||
ssize_t ret = sock.Recv(data, len, 0); // Optimistically try the recv first
|
||||
if (ret > 0) {
|
||||
@ -333,7 +333,7 @@ static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, c
|
||||
}
|
||||
if (interruptSocks5Recv)
|
||||
return IntrRecvError::Interrupted;
|
||||
curTime = GetTimeMillis();
|
||||
curTime = Now<SteadyMilliseconds>();
|
||||
}
|
||||
return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
|
||||
}
|
||||
|
@ -28,8 +28,8 @@
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
static int64_t nLastHeaderTipUpdateNotification = 0;
|
||||
static int64_t nLastBlockTipUpdateNotification = 0;
|
||||
static SteadyClock::time_point g_last_header_tip_update_notification{};
|
||||
static SteadyClock::time_point g_last_block_tip_update_notification{};
|
||||
|
||||
ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QObject *parent) :
|
||||
QObject(parent),
|
||||
@ -222,9 +222,9 @@ void ClientModel::TipChanged(SynchronizationState sync_state, interfaces::BlockT
|
||||
|
||||
// Throttle GUI notifications about (a) blocks during initial sync, and (b) both blocks and headers during reindex.
|
||||
const bool throttle = (sync_state != SynchronizationState::POST_INIT && synctype == SyncType::BLOCK_SYNC) || sync_state == SynchronizationState::INIT_REINDEX;
|
||||
const int64_t now = throttle ? GetTimeMillis() : 0;
|
||||
int64_t& nLastUpdateNotification = synctype != SyncType::BLOCK_SYNC ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
|
||||
if (throttle && now < nLastUpdateNotification + count_milliseconds(MODEL_UPDATE_DELAY)) {
|
||||
const auto now{throttle ? SteadyClock::now() : SteadyClock::time_point{}};
|
||||
auto& nLastUpdateNotification = synctype != SyncType::BLOCK_SYNC ? g_last_header_tip_update_notification : g_last_block_tip_update_notification;
|
||||
if (throttle && now < nLastUpdateNotification + MODEL_UPDATE_DELAY) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -141,10 +141,10 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
|
||||
BOOST_REQUIRE(filter_index.Start());
|
||||
|
||||
// Allow filter index to catch up with the block index.
|
||||
constexpr int64_t timeout_ms = 10 * 1000;
|
||||
int64_t time_start = GetTimeMillis();
|
||||
constexpr auto timeout{10s};
|
||||
const auto time_start{SteadyClock::now()};
|
||||
while (!filter_index.BlockUntilSyncedToCurrentChain()) {
|
||||
BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
|
||||
BOOST_REQUIRE(time_start + timeout > SteadyClock::now());
|
||||
UninterruptibleSleep(std::chrono::milliseconds{100});
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,11 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
int default_socks5_recv_timeout;
|
||||
};
|
||||
extern std::chrono::milliseconds g_socks5_recv_timeout;
|
||||
|
||||
extern int g_socks5_recv_timeout;
|
||||
namespace {
|
||||
decltype(g_socks5_recv_timeout) default_socks5_recv_timeout;
|
||||
};
|
||||
|
||||
void initialize_socks5()
|
||||
{
|
||||
@ -35,7 +35,7 @@ FUZZ_TARGET_INIT(socks5, initialize_socks5)
|
||||
InterruptSocks5(fuzzed_data_provider.ConsumeBool());
|
||||
// Set FUZZED_SOCKET_FAKE_LATENCY=1 to exercise recv timeout code paths. This
|
||||
// will slow down fuzzing.
|
||||
g_socks5_recv_timeout = (fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) ? 1 : default_socks5_recv_timeout;
|
||||
g_socks5_recv_timeout = (fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) ? 1ms : default_socks5_recv_timeout;
|
||||
FuzzedSock fuzzed_sock = ConsumeSock(fuzzed_data_provider);
|
||||
// This Socks5(...) fuzzing harness would have caught CVE-2017-18350 within
|
||||
// a few seconds of fuzzing.
|
||||
|
@ -32,10 +32,10 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
|
||||
BOOST_REQUIRE(txindex.Start());
|
||||
|
||||
// Allow tx index to catch up with the block index.
|
||||
constexpr int64_t timeout_ms = 10 * 1000;
|
||||
int64_t time_start = GetTimeMillis();
|
||||
constexpr auto timeout{10s};
|
||||
const auto time_start{SteadyClock::now()};
|
||||
while (!txindex.BlockUntilSyncedToCurrentChain()) {
|
||||
BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
|
||||
BOOST_REQUIRE(time_start + timeout > SteadyClock::now());
|
||||
UninterruptibleSleep(std::chrono::milliseconds{100});
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ static RPCHelpMan getwalletinfo()
|
||||
obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
|
||||
if (pwallet->IsScanning()) {
|
||||
UniValue scanning(UniValue::VOBJ);
|
||||
scanning.pushKV("duration", pwallet->ScanningDuration() / 1000);
|
||||
scanning.pushKV("duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
|
||||
scanning.pushKV("progress", pwallet->ScanningProgress());
|
||||
obj.pushKV("scanning", scanning);
|
||||
} else {
|
||||
|
@ -559,13 +559,14 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
|
||||
return false;
|
||||
if (Unlock(_vMasterKey))
|
||||
{
|
||||
int64_t nStartTime = GetTimeMillis();
|
||||
constexpr MillisecondsDouble target{100};
|
||||
auto start{SteadyClock::now()};
|
||||
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
|
||||
pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))));
|
||||
pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
|
||||
|
||||
nStartTime = GetTimeMillis();
|
||||
start = SteadyClock::now();
|
||||
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
|
||||
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
|
||||
pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
|
||||
|
||||
if (pMasterKey.second.nDeriveIterations < 25000)
|
||||
pMasterKey.second.nDeriveIterations = 25000;
|
||||
@ -762,13 +763,14 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||
GetStrongRandBytes(kMasterKey.vchSalt);
|
||||
|
||||
CCrypter crypter;
|
||||
int64_t nStartTime = GetTimeMillis();
|
||||
constexpr MillisecondsDouble target{100};
|
||||
auto start{SteadyClock::now()};
|
||||
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
|
||||
kMasterKey.nDeriveIterations = static_cast<unsigned int>(2500000 / ((double)(GetTimeMillis() - nStartTime)));
|
||||
kMasterKey.nDeriveIterations = static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
|
||||
|
||||
nStartTime = GetTimeMillis();
|
||||
start = SteadyClock::now();
|
||||
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
|
||||
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
|
||||
kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
|
||||
|
||||
if (kMasterKey.nDeriveIterations < 25000)
|
||||
kMasterKey.nDeriveIterations = 25000;
|
||||
|
@ -284,7 +284,7 @@ private:
|
||||
std::atomic<bool> fScanningWallet{false}; // controlled by WalletRescanReserver
|
||||
std::atomic<bool> m_attaching_chain{false};
|
||||
std::atomic<bool> m_scanning_with_passphrase{false};
|
||||
std::atomic<int64_t> m_scanning_start{0};
|
||||
std::atomic<SteadyClock::time_point> m_scanning_start{SteadyClock::time_point{}};
|
||||
std::atomic<double> m_scanning_progress{0};
|
||||
friend class WalletRescanReserver;
|
||||
|
||||
@ -505,7 +505,7 @@ public:
|
||||
bool IsAbortingRescan() const { return fAbortRescan; }
|
||||
bool IsScanning() const { return fScanningWallet; }
|
||||
bool IsScanningWithPassphrase() const { return m_scanning_with_passphrase; }
|
||||
int64_t ScanningDuration() const { return fScanningWallet ? GetTimeMillis() - m_scanning_start : 0; }
|
||||
SteadyClock::duration ScanningDuration() const { return fScanningWallet ? SteadyClock::now() - m_scanning_start.load() : SteadyClock::duration{}; }
|
||||
double ScanningProgress() const { return fScanningWallet ? (double) m_scanning_progress : 0; }
|
||||
|
||||
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
|
||||
@ -1014,7 +1014,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
m_wallet.m_scanning_with_passphrase.exchange(with_passphrase);
|
||||
m_wallet.m_scanning_start = GetTimeMillis();
|
||||
m_wallet.m_scanning_start = SteadyClock::now();
|
||||
m_wallet.m_scanning_progress = 0;
|
||||
m_could_reserve = true;
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user