In 2038 the epoch time run out of bits and that makes it need more bits to represent the correct datetime.
-
IamLupo commented at 4:03 AM on March 4, 2021: none
- IamLupo added the label Bug on Mar 4, 2021
-
7hacker commented at 4:20 AM on March 4, 2021: none
I believe bitcoin uses unsigned 32-bit time types so the problem if any is delayed to 2106
-
IamLupo commented at 4:29 AM on March 4, 2021: none
I believe bitcoin uses unsigned 32-bit time types so the problem if any is delayed to 2106
Well the hole project uses int64_t GetTime(): https://github.com/bitcoin/bitcoin/blob/master/src/util/time.cpp#L26
If you read this function you see he uses the time() function through the OS to get the epoch time.
And if i read the specifications from linux about this call: https://man7.org/linux/man-pages/man2/time.2.html
On Linux, a call to time() with tloc specified as NULL cannot fail with the error EOVERFLOW, even on ABIs where time_t is a signed 32-bit integer and the clock ticks past the time 2**31 (2038-01-19 03:14:08 UTC, ignoring leap seconds). (POSIX.1 permits, but does not require, the EOVERFLOW error in the case where the seconds since the Epoch will not fit in time_t.) Instead, the behavior on Linux is undefined when the system time is out of the time_t range. Applications intended to run after 2038 should use ABIs with time_t wider than 32 bits. Basicly i dont see in the project that it uses ABI's with time_t.
Also if there is a unsigned 32-bit declaired then that doesnt mean the time() function will also generate this. In this case its a time_t value. That is treated different.
-
7hacker commented at 4:42 AM on March 4, 2021: none
That call appears deprecated. See util/time.h
/** * DEPRECATED * Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable) */ int64_t GetTime(); -
IamLupo commented at 5:39 AM on March 4, 2021: none
I also read that this apperntly will get fixed by itself over time. Like basicly its not a big issue anymore. Just a recompile over time.
If you write C++ code using chrono::system_clock or chrono::steady_clock now and update ESP-IDF once the 2038 problem is solved, the code should keep working after 2038 with just a recompile against the newer libc & libstdc++. - laanwj added the label Brainstorming on Mar 4, 2021
-
laanwj commented at 9:39 AM on March 4, 2021: member
It would be good to have a test for this. (e.g. what happens to a running
bitcoindat the epoch, starting one after it, etc) - laanwj added the label Tests on Mar 4, 2021
-
maflcko commented at 4:02 PM on March 5, 2021: member
Side-note: It is also possible to run the tests under a specific time. E.g.
faketime -f '+3y' ./test/functional/wallet_disable.py. -
IamLupo commented at 3:21 AM on March 6, 2021: none
I made a small script:
#include <iostream> #include <chrono> #include <cstdint> #include <cassert> using namespace std; int total_bits(uint64_t epoch) { int i = 0; while(epoch != 0) { epoch /= 2; i++; } return i; } 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; } int main() { int64_t epoch; cout << "set date '2038-01-01'" << endl; system("date +%Y%m%d -s '20380101'"); epoch = int64_t{GetSystemTime<std::chrono::seconds>().count()}; cout << "epoch = " << epoch << " (bits: " << total_bits(epoch) << ")" << endl; system("date +%Y%m%d -s '20380201'"); cout << "set date '2038-02-01'" << endl; epoch = int64_t{GetSystemTime<std::chrono::seconds>().count()}; cout << "epoch = " << epoch << " (bits: " << total_bits(epoch) << ")" << endl; system("date +%Y%m%d -s '21060201'"); cout << "set date '2106-02-01'" << endl; epoch = int64_t{GetSystemTime<std::chrono::seconds>().count()}; cout << "epoch = " << epoch << " (bits: " << total_bits(epoch) << ")" << endl; system("date +%Y%m%d -s '21060301'"); cout << "set date '2106-03-01'" << endl; epoch = int64_t{GetSystemTime<std::chrono::seconds>().count()}; cout << "epoch = " << epoch << " (bits: " << total_bits(epoch) << ")" << endl; return 0; }Result:
iamlupo@iamlupo-VM2:/var/www/EpochTime2038$ sudo ./main set date '2038-01-01' 20380101 epoch = 2145913200 (bits: 31) 20380201 set date '2038-02-01' epoch = 2148591600 (bits: 32) 21060201 set date '2106-02-01' epoch = 4294422000 (bits: 32) 21060301 set date '2106-03-01' epoch = 4296841200 (bits: 33)Basicly this tells me the std:chrono works correctly on my linux vm.
iamlupo@iamlupo-VM2:/var/www/EpochTime2038$ uname -a Linux iamlupo-VM2 5.8.0-43-generic [#49](/bitcoin-bitcoin/49/)-Ubuntu SMP Fri Feb 5 03:01:28 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux iamlupo@iamlupo-VM2:/var/www/EpochTime2038$ g++ --version g++ (Ubuntu 10.2.0-13ubuntu1) 10.2.0 Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.This should be tested between different compilers and os's to figure out if all of them has patched std::chrono correctly and since what version its been patched. That you can avoid old compilers.
Second will be that all parts where a time is been used needs to be patched fron unsigned int/uint32_t to int64_t.
As example here: https://github.com/bitcoin/bitcoin/blob/4a540683ec40393d6369da1a9e02e45614db936d/src/primitives/block.h#L27
-
garlonicon commented at 3:35 AM on October 14, 2021: none
Patching
block.hwill affect mining, because if you replaceuint32_t nTimewith something wider than 32-bit value, then patched block headers will be backward-incompatible. That would mean a hard-fork. -
carnhofdaki commented at 7:53 AM on May 15, 2022: contributor
If this
nTimewas used merely for computing the difficulty, it can stayuint32_tand the only thing requiring change would be something like adding a conditionif block_time_2016_back > block_time_now { do_simple_magic; }which would normalize (offset) both of the two values (the overflown lower and before-overflow bigger, rendering them like they are supposed to be) and carry on with the difficulty computation like normal. Yes, it would require some minimum Bitcoin Core version, but the sooner it gets implemented, the sooner are compatible nodes running. The fix can be also easily back-ported to older stable branches.Is my thinking right that the the related value of
uint32_ttype stored in each block can be (or already is?) used merely in difficulty computation so that everything can stay as it is and no hard-fork is needed? - maflcko removed the label Bug on Oct 5, 2022
- fanquake closed this on Oct 21, 2022
- sidhujag referenced this in commit ac491b0e47 on Oct 23, 2022
- bitcoin locked this on Oct 21, 2023