mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 02:25:40 +01:00
Merge #21110: util: remove Boost posix_time usage from GetTime*
9266f7497f
util: Use std::chrono for time getters (MarcoFalke)3c2e16be22
time: add runtime sanity check (Cory Fields) Pull request description: I have a followup that should remove the last of our `boost:posix_time` usage in `ParseISO8601DateTime`, but that will likely need more cross-platform testing/discussion, so have just split them up as this change is straight forward. ACKs for top commit: practicalswift: Tested ACK9266f7497f
laanwj: Code review ACK9266f7497f
Tree-SHA512: 5471a60e65e9fa8ef48320743ef637f1d162724e717e0f5509118e1e5732fc0844656a9c09d3d1300eb657dcc7a1e1e67305d8c9ef959c63be67393607dd4ceb
This commit is contained in:
commit
372dd8da24
@ -773,6 +773,10 @@ static bool InitSanityCheck()
|
||||
return InitError(Untranslated("OS cryptographic RNG sanity check failure. Aborting."));
|
||||
}
|
||||
|
||||
if (!ChronoSanityCheck()) {
|
||||
return InitError(Untranslated("Clock epoch mismatch. Aborting."));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <compat/sanity.h>
|
||||
#include <key.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <util/time.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
@ -15,6 +16,7 @@ BOOST_AUTO_TEST_CASE(basic_sanity)
|
||||
BOOST_CHECK_MESSAGE(glibc_sanity_test() == true, "libc sanity test");
|
||||
BOOST_CHECK_MESSAGE(glibcxx_sanity_test() == true, "stdlib sanity test");
|
||||
BOOST_CHECK_MESSAGE(ECC_InitSanityCheck() == true, "secp256k1 sanity test");
|
||||
BOOST_CHECK_MESSAGE(ChronoSanityCheck() == true, "chrono epoch test");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -33,6 +33,49 @@ int64_t GetTime()
|
||||
return now;
|
||||
}
|
||||
|
||||
bool ChronoSanityCheck()
|
||||
{
|
||||
// std::chrono::system_clock.time_since_epoch and time_t(0) are not guaranteed
|
||||
// to use the Unix epoch timestamp, prior to C++20, but in practice they almost
|
||||
// certainly will. Any differing behavior will be assumed to be an error, unless
|
||||
// certain platforms prove to consistently deviate, at which point we'll cope
|
||||
// with it by adding offsets.
|
||||
|
||||
// Create a new clock from time_t(0) and make sure that it represents 0
|
||||
// seconds from the system_clock's time_since_epoch. Then convert that back
|
||||
// to a time_t and verify that it's the same as before.
|
||||
const time_t time_t_epoch{};
|
||||
auto clock = std::chrono::system_clock::from_time_t(time_t_epoch);
|
||||
if (std::chrono::duration_cast<std::chrono::seconds>(clock.time_since_epoch()).count() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
time_t time_val = std::chrono::system_clock::to_time_t(clock);
|
||||
if (time_val != time_t_epoch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the above zero time is actually equal to the known unix timestamp.
|
||||
struct tm epoch;
|
||||
#ifdef HAVE_GMTIME_R
|
||||
if (gmtime_r(&time_val, &epoch) == nullptr) {
|
||||
#else
|
||||
if (gmtime_s(&epoch, &time_val) != 0) {
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((epoch.tm_sec != 0) ||
|
||||
(epoch.tm_min != 0) ||
|
||||
(epoch.tm_hour != 0) ||
|
||||
(epoch.tm_mday != 1) ||
|
||||
(epoch.tm_mon != 0) ||
|
||||
(epoch.tm_year != 70)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T GetTime()
|
||||
{
|
||||
@ -47,6 +90,14 @@ template std::chrono::seconds GetTime();
|
||||
template std::chrono::milliseconds GetTime();
|
||||
template std::chrono::microseconds GetTime();
|
||||
|
||||
template <typename T>
|
||||
static T GetSystemTime()
|
||||
{
|
||||
const auto now = std::chrono::duration_cast<T>(std::chrono::system_clock::now().time_since_epoch());
|
||||
assert(now.count() > 0);
|
||||
return now;
|
||||
}
|
||||
|
||||
void SetMockTime(int64_t nMockTimeIn)
|
||||
{
|
||||
Assert(nMockTimeIn >= 0);
|
||||
@ -65,23 +116,17 @@ std::chrono::seconds GetMockTime()
|
||||
|
||||
int64_t GetTimeMillis()
|
||||
{
|
||||
int64_t now = (boost::posix_time::microsec_clock::universal_time() -
|
||||
boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds();
|
||||
assert(now > 0);
|
||||
return now;
|
||||
return int64_t{GetSystemTime<std::chrono::milliseconds>().count()};
|
||||
}
|
||||
|
||||
int64_t GetTimeMicros()
|
||||
{
|
||||
int64_t now = (boost::posix_time::microsec_clock::universal_time() -
|
||||
boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
|
||||
assert(now > 0);
|
||||
return now;
|
||||
return int64_t{GetSystemTime<std::chrono::microseconds>().count()};
|
||||
}
|
||||
|
||||
int64_t GetSystemTimeInSeconds()
|
||||
{
|
||||
return GetTimeMicros()/1000000;
|
||||
return int64_t{GetSystemTime<std::chrono::seconds>().count()};
|
||||
}
|
||||
|
||||
std::string FormatISO8601DateTime(int64_t nTime) {
|
||||
|
@ -79,4 +79,7 @@ struct timeval MillisToTimeval(int64_t nTimeout);
|
||||
*/
|
||||
struct timeval MillisToTimeval(std::chrono::milliseconds ms);
|
||||
|
||||
/** Sanity check epoch match normal Unix epoch */
|
||||
bool ChronoSanityCheck();
|
||||
|
||||
#endif // BITCOIN_UTIL_TIME_H
|
||||
|
Loading…
Reference in New Issue
Block a user