Fabcoin Core  0.16.2
P2P Digital Currency
timedata.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2017 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.
4 
5 #if defined(HAVE_CONFIG_H)
7 #endif
8 
9 #include <timedata.h>
10 
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>
17 
18 
19 static CCriticalSection cs_nTimeOffset;
20 static int64_t nTimeOffset = 0;
21 
29 int64_t GetTimeOffset()
30 {
31  LOCK(cs_nTimeOffset);
32  return nTimeOffset;
33 }
34 
35 int64_t GetAdjustedTime()
36 {
37  return GetTime() + GetTimeOffset();
38 }
39 
40 static int64_t abs64(int64_t n)
41 {
42  return (n >= 0 ? n : -n);
43 }
44 
45 #define FABCOIN_TIMEDATA_MAX_SAMPLES 200
46 
47 void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
48 {
49  LOCK(cs_nTimeOffset);
50  // Ignore duplicates
51  static std::set<CNetAddr> setKnown;
52  if (setKnown.size() == FABCOIN_TIMEDATA_MAX_SAMPLES)
53  return;
54  if (!setKnown.insert(ip).second)
55  return;
56 
57  // Add data
59  vTimeOffsets.input(nOffsetSample);
60  LogPrint(BCLog::NET,"added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
61 
62  // There is a known issue here (see issue #4521):
63  //
64  // - The structure vTimeOffsets contains up to 200 elements, after which
65  // any new element added to it will not increase its size, replacing the
66  // oldest element.
67  //
68  // - The condition to update nTimeOffset includes checking whether the
69  // number of elements in vTimeOffsets is odd, which will never happen after
70  // there are 200 elements.
71  //
72  // But in this case the 'bug' is protective against some attacks, and may
73  // actually explain why we've never seen attacks which manipulate the
74  // clock offset.
75  //
76  // So we should hold off on fixing this and clean it up as part of
77  // a timing cleanup that strengthens it in a number of other ways.
78  //
79  if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
80  {
81  int64_t nMedian = vTimeOffsets.median();
82  std::vector<int64_t> vSorted = vTimeOffsets.sorted();
83  // Only let other nodes change our time by so much
84  if (abs64(nMedian) <= std::max<int64_t>(0, gArgs.GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT)))
85  {
86  nTimeOffset = nMedian;
87  }
88  else
89  {
90  nTimeOffset = 0;
91 
92  static bool fDone;
93  if (!fDone)
94  {
95  // If nobody has a time different than ours but within 5 minutes of ours, give a warning
96  bool fMatch = false;
97  for (int64_t nOffset : vSorted)
98  if (nOffset != 0 && abs64(nOffset) < 5 * 60)
99  fMatch = true;
100 
101  if (!fMatch)
102  {
103  fDone = true;
104  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));
105  SetMiscWarning(strMessage);
107  }
108  }
109  }
110 
111  if (LogAcceptCategory(BCLog::NET)) {
112  for (int64_t n : vSorted) {
113  LogPrint(BCLog::NET, "%+d ", n);
114  }
115  LogPrint(BCLog::NET, "| ");
116 
117  LogPrint(BCLog::NET, "nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
118  }
119  }
120 }
#define PACKAGE_NAME
#define strprintf
Definition: tinyformat.h:1054
Median filter over a stream of values.
Definition: timedata.h:22
int64_t GetTimeOffset()
"Never go to sea with two chronometers; take one or three." Our three time sources are: ...
Definition: timedata.cpp:29
void input(T value)
Definition: timedata.h:37
#define LOCK(cs)
Definition: sync.h:175
T median() const
Definition: timedata.h:49
#define FABCOIN_TIMEDATA_MAX_SAMPLES
Definition: timedata.cpp:45
#define LogPrint(category,...)
Definition: util.h:164
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:31
int size() const
Definition: timedata.h:62
ArgsManager gArgs
Definition: util.cpp:94
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Return string argument or default value.
Definition: util.cpp:504
int64_t GetAdjustedTime()
Definition: timedata.cpp:35
void SetMiscWarning(const std::string &strWarning)
Definition: warnings.cpp:16
boost::signals2::signal< bool(const std::string &message, const std::string &caption, unsigned int style), boost::signals2::last_value< bool > > ThreadSafeMessageBox
Show message box.
Definition: ui_interface.h:75
std::vector< T > sorted() const
Definition: timedata.h:67
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units...
Definition: utiltime.cpp:19
CClientUIInterface uiInterface
Definition: ui_interface.cpp:8
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
Definition: timedata.cpp:47
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
Definition: util.h:71
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
Definition: sync.h:91