diff --git a/configure.ac b/configure.ac index 964b7d0942f..ba7e0dea825 100644 --- a/configure.ac +++ b/configure.ac @@ -1086,22 +1086,6 @@ if test "$use_thread_local" = "yes" || test "$use_thread_local" = "auto"; then LDFLAGS="$TEMP_LDFLAGS" fi -dnl check for gmtime_r(), fallback to gmtime_s() if that is unavailable -dnl fail if neither are available. -AC_MSG_CHECKING([for gmtime_r]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[ gmtime_r((const time_t *) nullptr, (struct tm *) nullptr); ]])], - [ AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_GMTIME_R], [1], [Define this symbol if gmtime_r is available]) ], - [ AC_MSG_RESULT([no]); - AC_MSG_CHECKING([for gmtime_s]); - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[ gmtime_s((struct tm *) nullptr, (const time_t *) nullptr); ]])], - [ AC_MSG_RESULT([yes])], - [ AC_MSG_RESULT([no]); AC_MSG_ERROR([Both gmtime_r and gmtime_s are unavailable]) ] - ) - ] -) - dnl Check for different ways of gathering OS randomness AC_MSG_CHECKING([for Linux getrandom function]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @@ -1862,7 +1846,6 @@ AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) AC_SUBST(NATPMP_CPPFLAGS) AC_SUBST(NATPMP_LIBS) -AC_SUBST(HAVE_GMTIME_R) AC_SUBST(HAVE_FDATASYNC) AC_SUBST(HAVE_FULLFSYNC) AC_SUBST(HAVE_O_CLOEXEC) diff --git a/src/kernel/checks.cpp b/src/kernel/checks.cpp index bf8a2ec74c0..45a5e25093f 100644 --- a/src/kernel/checks.cpp +++ b/src/kernel/checks.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -23,10 +22,6 @@ util::Result SanityChecks(const Context&) return util::Error{Untranslated("OS cryptographic RNG sanity check failure. Aborting.")}; } - if (!ChronoSanityCheck()) { - return util::Error{Untranslated("Clock epoch mismatch. Aborting.")}; - } - return {}; } diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp index 451bc99d446..68f82b760cc 100644 --- a/src/test/sanity_tests.cpp +++ b/src/test/sanity_tests.cpp @@ -4,7 +4,6 @@ #include #include -#include #include @@ -13,7 +12,6 @@ BOOST_FIXTURE_TEST_SUITE(sanity_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(basic_sanity) { BOOST_CHECK_MESSAGE(ECC_InitSanityCheck() == true, "secp256k1 sanity test"); - BOOST_CHECK_MESSAGE(ChronoSanityCheck() == true, "chrono epoch test"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 47808a2a581..9a2add748e5 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -290,13 +290,18 @@ BOOST_AUTO_TEST_CASE(util_TrimString) BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTime) { + BOOST_CHECK_EQUAL(FormatISO8601DateTime(971890963199), "32767-12-31T23:59:59Z"); + BOOST_CHECK_EQUAL(FormatISO8601DateTime(971890876800), "32767-12-31T00:00:00Z"); BOOST_CHECK_EQUAL(FormatISO8601DateTime(1317425777), "2011-09-30T23:36:17Z"); BOOST_CHECK_EQUAL(FormatISO8601DateTime(0), "1970-01-01T00:00:00Z"); } BOOST_AUTO_TEST_CASE(util_FormatISO8601Date) { + BOOST_CHECK_EQUAL(FormatISO8601Date(971890963199), "32767-12-31"); + BOOST_CHECK_EQUAL(FormatISO8601Date(971890876800), "32767-12-31"); BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30"); + BOOST_CHECK_EQUAL(FormatISO8601Date(0), "1970-01-01"); } BOOST_AUTO_TEST_CASE(util_FormatMoney) diff --git a/src/util/time.cpp b/src/util/time.cpp index 5ca9d21f8d0..456662bd842 100644 --- a/src/util/time.cpp +++ b/src/util/time.cpp @@ -3,70 +3,21 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#if defined(HAVE_CONFIG_H) -#include -#endif +#include #include #include -#include #include #include #include -#include -#include -#include -#include #include +#include void UninterruptibleSleep(const std::chrono::microseconds& n) { std::this_thread::sleep_for(n); } static std::atomic nMockTime(0); //!< For testing -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(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; -} - NodeClock::time_point NodeClock::now() noexcept { const std::chrono::seconds mocktime{nMockTime.load(std::memory_order_relaxed)}; @@ -96,30 +47,21 @@ std::chrono::seconds GetMockTime() int64_t GetTime() { return GetTime().count(); } -std::string FormatISO8601DateTime(int64_t nTime) { - struct tm ts; - time_t time_val = nTime; -#ifdef HAVE_GMTIME_R - if (gmtime_r(&time_val, &ts) == nullptr) { -#else - if (gmtime_s(&ts, &time_val) != 0) { -#endif - return {}; - } - return strprintf("%04i-%02i-%02iT%02i:%02i:%02iZ", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec); +std::string FormatISO8601DateTime(int64_t nTime) +{ + const std::chrono::sys_seconds secs{std::chrono::seconds{nTime}}; + const auto days{std::chrono::floor(secs)}; + const std::chrono::year_month_day ymd{days}; + const std::chrono::hh_mm_ss hms{secs - days}; + return strprintf("%04i-%02u-%02uT%02i:%02i:%02iZ", signed{ymd.year()}, unsigned{ymd.month()}, unsigned{ymd.day()}, hms.hours().count(), hms.minutes().count(), hms.seconds().count()); } -std::string FormatISO8601Date(int64_t nTime) { - struct tm ts; - time_t time_val = nTime; -#ifdef HAVE_GMTIME_R - if (gmtime_r(&time_val, &ts) == nullptr) { -#else - if (gmtime_s(&ts, &time_val) != 0) { -#endif - return {}; - } - return strprintf("%04i-%02i-%02i", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday); +std::string FormatISO8601Date(int64_t nTime) +{ + const std::chrono::sys_seconds secs{std::chrono::seconds{nTime}}; + const auto days{std::chrono::floor(secs)}; + const std::chrono::year_month_day ymd{days}; + return strprintf("%04i-%02u-%02u", signed{ymd.year()}, unsigned{ymd.month()}, unsigned{ymd.day()}); } struct timeval MillisToTimeval(int64_t nTimeout) diff --git a/src/util/time.h b/src/util/time.h index 6aa776137c1..108560e0e0c 100644 --- a/src/util/time.h +++ b/src/util/time.h @@ -116,7 +116,4 @@ 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