Closed kristapsk closed 3 years ago
Damn!
This is basically the year 2038 problem. That is only 17 years from now. It's plausible that JoinMarket would exist 10-20 years from now and/or that someone wants to lock up coins for a decade or two to use a fidelity bond. So it's not a good solution to just disable those dates.
Bitcoin itself has a similar problem in block headers but because it uses an unsigned integer the wraparound date is in the 22nd century. Is there a way we can have 32bit python use an unsigned integer?
@chris-belcher would you be addressing this as part of your recent fidelity bond work?
I don't know how. I haven't thought about it much yet.
OK I did some searching and found a solution to the 2038 problem on python I think.
All we need to do is have a way to change unix timestamps into datetimes (year, month, day etc), and datetimes into timestamps.
>>> import datetime
>>> from calendar import timegm
>>> timegm(datetime.datetime(2040, 1, 1, 0, 0, 0, 0).timetuple()) ###converting (year,month) into unix time works
2208988800
>>> datetime.datetime.utcfromtimestamp(2208988800) ###converting that unix time to (year, month) fails on this 32 bit system
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: timestamp out of range for platform time_t
>>> datetime.datetime.utcfromtimestamp(0) + datetime.timedelta(seconds=2208988800) ###using this trick from the stackoverflow thread does work
datetime.datetime(2040, 1, 1, 1, 0)
>>>
So it's actually a one line edit once you find the stackoverflow thread telling you what to do.
However this will require some testing because the stackoverflow thread says there might be timezone issues.
EDIT: the machine I'm testing this on is on the greenwich timezone, so its offset seems to be zero. Could someone else try it if they have a 32 bit platform on another timezone? All you do is run the following code and change the years/months/days/hours around to check that the resulting datetime always matches what you wrote.
>>> import datetime
>>> from calendar import timegm
>>> datetime.datetime.utcfromtimestamp(0) + datetime.timedelta(seconds=timegm(datetime.datetime(2070, 1, 1, 10, 0, 0, 0).timetuple()))
datetime.datetime(2070, 1, 1, 10, 0)
EDIT2: Looks like I can make timezone become an issue if I use datetime.fromtimestamp()
instead of datetime.utcfromtimestamp
. If so then the solution is to use the utcfromtimestamp function, and that's all we need. The fix really is a one line edit.
Noticed while testing #796 on armv7l (although modern Raspberry Pi's are technically 64-bit boards, default Linux used there is still 32-bit). Guess we could just remove locktimes after year 2038 there? Or we should add support for years above 2038 on archs where
time_t
is 32-bit? Ping @chris-belcher.