1 // Copyright (c) 2014 The Bitcoin developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
9 #include "ui_interface.h"
11 #include "utilstrencodings.h"
13 #include <boost/foreach.hpp>
17 static CCriticalSection cs_nTimeOffset;
18 static int64_t nTimeOffset = 0;
21 * "Never go to sea with two chronometers; take one or three."
22 * Our three time sources are:
24 * - Median of other nodes clocks
25 * - The user (asking the user to fix the system clock if the first two disagree)
27 int64_t GetTimeOffset()
33 int64_t GetAdjustedTime()
35 return GetTime() + GetTimeOffset();
38 static int64_t abs64(int64_t n)
40 return (n >= 0 ? n : -n);
43 void AddTimeData(const CNetAddr& ip, int64_t nTime)
45 int64_t nOffsetSample = nTime - GetTime();
49 static set<CNetAddr> setKnown;
50 if (!setKnown.insert(ip).second)
54 static CMedianFilter<int64_t> vTimeOffsets(200,0);
55 vTimeOffsets.input(nOffsetSample);
56 LogPrintf("Added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
58 // There is a known issue here (see issue #4521):
60 // - The structure vTimeOffsets contains up to 200 elements, after which
61 // any new element added to it will not increase its size, replacing the
64 // - The condition to update nTimeOffset includes checking whether the
65 // number of elements in vTimeOffsets is odd, which will never happen after
66 // there are 200 elements.
68 // But in this case the 'bug' is protective against some attacks, and may
69 // actually explain why we've never seen attacks which manipulate the
72 // So we should hold off on fixing this and clean it up as part of
73 // a timing cleanup that strengthens it in a number of other ways.
75 if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
77 int64_t nMedian = vTimeOffsets.median();
78 std::vector<int64_t> vSorted = vTimeOffsets.sorted();
79 // Only let other nodes change our time by so much
80 if (abs64(nMedian) < 70 * 60)
82 nTimeOffset = nMedian;
91 // If nobody has a time different than ours but within 5 minutes of ours, give a warning
93 BOOST_FOREACH(int64_t nOffset, vSorted)
94 if (nOffset != 0 && abs64(nOffset) < 5 * 60)
100 string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Bitcoin Core will not work properly.");
101 strMiscWarning = strMessage;
102 LogPrintf("*** %s\n", strMessage);
103 uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
108 BOOST_FOREACH(int64_t n, vSorted)
109 LogPrintf("%+d ", n);
112 LogPrintf("nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60);