Merge #9966: Control mempool persistence using a command line parameter
[bitcoinplatinum.git] / src / timedata.cpp
blobec749127032b643053fa88625f9a2e8fad2abe51
1 // Copyright (c) 2014-2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #if defined(HAVE_CONFIG_H)
6 #include "config/bitcoin-config.h"
7 #endif
9 #include "timedata.h"
11 #include "netaddress.h"
12 #include "sync.h"
13 #include "ui_interface.h"
14 #include "util.h"
15 #include "utilstrencodings.h"
16 #include "warnings.h"
18 #include <boost/foreach.hpp>
20 static CCriticalSection cs_nTimeOffset;
21 static int64_t nTimeOffset = 0;
23 /**
24 * "Never go to sea with two chronometers; take one or three."
25 * Our three time sources are:
26 * - System clock
27 * - Median of other nodes clocks
28 * - The user (asking the user to fix the system clock if the first two disagree)
30 int64_t GetTimeOffset()
32 LOCK(cs_nTimeOffset);
33 return nTimeOffset;
36 int64_t GetAdjustedTime()
38 return GetTime() + GetTimeOffset();
41 static int64_t abs64(int64_t n)
43 return (n >= 0 ? n : -n);
46 #define BITCOIN_TIMEDATA_MAX_SAMPLES 200
48 void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
50 LOCK(cs_nTimeOffset);
51 // Ignore duplicates
52 static std::set<CNetAddr> setKnown;
53 if (setKnown.size() == BITCOIN_TIMEDATA_MAX_SAMPLES)
54 return;
55 if (!setKnown.insert(ip).second)
56 return;
58 // Add data
59 static CMedianFilter<int64_t> vTimeOffsets(BITCOIN_TIMEDATA_MAX_SAMPLES, 0);
60 vTimeOffsets.input(nOffsetSample);
61 LogPrint(BCLog::NET,"added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
63 // There is a known issue here (see issue #4521):
65 // - The structure vTimeOffsets contains up to 200 elements, after which
66 // any new element added to it will not increase its size, replacing the
67 // oldest element.
69 // - The condition to update nTimeOffset includes checking whether the
70 // number of elements in vTimeOffsets is odd, which will never happen after
71 // there are 200 elements.
73 // But in this case the 'bug' is protective against some attacks, and may
74 // actually explain why we've never seen attacks which manipulate the
75 // clock offset.
77 // So we should hold off on fixing this and clean it up as part of
78 // a timing cleanup that strengthens it in a number of other ways.
80 if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
82 int64_t nMedian = vTimeOffsets.median();
83 std::vector<int64_t> vSorted = vTimeOffsets.sorted();
84 // Only let other nodes change our time by so much
85 if (abs64(nMedian) <= std::max<int64_t>(0, GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT)))
87 nTimeOffset = nMedian;
89 else
91 nTimeOffset = 0;
93 static bool fDone;
94 if (!fDone)
96 // If nobody has a time different than ours but within 5 minutes of ours, give a warning
97 bool fMatch = false;
98 BOOST_FOREACH(int64_t nOffset, vSorted)
99 if (nOffset != 0 && abs64(nOffset) < 5 * 60)
100 fMatch = true;
102 if (!fMatch)
104 fDone = true;
105 std::string strMessage = strprintf(_("Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly."), _(PACKAGE_NAME));
106 SetMiscWarning(strMessage);
107 uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
112 if (LogAcceptCategory(BCLog::NET)) {
113 BOOST_FOREACH(int64_t n, vSorted) {
114 LogPrint(BCLog::NET, "%+d ", n);
116 LogPrint(BCLog::NET, "| ");
118 LogPrint(BCLog::NET, "nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60);