Raven Core  3.0.0
P2P Digital Currency
timedata.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2016 The Bitcoin Core developers
2 // Copyright (c) 2017-2019 The Raven Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #if defined(HAVE_CONFIG_H)
7 #include "config/raven-config.h"
8 #endif
9 
10 #include "timedata.h"
11 
12 #include "netaddress.h"
13 #include "sync.h"
14 #include "ui_interface.h"
15 #include "util.h"
16 #include "utilstrencodings.h"
17 #include "warnings.h"
18 
19 
20 static CCriticalSection cs_nTimeOffset;
21 static int64_t nTimeOffset = 0;
22 
30 int64_t GetTimeOffset()
31 {
32  LOCK(cs_nTimeOffset);
33  return nTimeOffset;
34 }
35 
36 int64_t GetAdjustedTime()
37 {
38  return GetTime() + GetTimeOffset();
39 }
40 
41 static int64_t abs64(int64_t n)
42 {
43  return (n >= 0 ? n : -n);
44 }
45 
46 #define RAVEN_TIMEDATA_MAX_SAMPLES 200
47 
48 void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
49 {
50  LOCK(cs_nTimeOffset);
51  // Ignore duplicates
52  static std::set<CNetAddr> setKnown;
53  if (setKnown.size() == RAVEN_TIMEDATA_MAX_SAMPLES)
54  return;
55  if (!setKnown.insert(ip).second)
56  return;
57 
58  // Add data
59  static CMedianFilter<int64_t> vTimeOffsets(RAVEN_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);
62 
63  // There is a known issue here (see issue #4521):
64  //
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.
68  //
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.
72  //
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.
76  //
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.
79  //
80  if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
81  {
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, gArgs.GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT)))
86  {
87  nTimeOffset = nMedian;
88  }
89  else
90  {
91  nTimeOffset = 0;
92 
93  static bool fDone;
94  if (!fDone)
95  {
96  // If nobody has a time different than ours but within 5 minutes of ours, give a warning
97  bool fMatch = false;
98  for (int64_t nOffset : vSorted)
99  if (nOffset != 0 && abs64(nOffset) < 5 * 60)
100  fMatch = true;
101 
102  if (!fMatch)
103  {
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);
108  }
109  }
110  }
111 
112  if (LogAcceptCategory(BCLog::NET)) {
113  for (int64_t n : vSorted) {
114  LogPrint(BCLog::NET, "%+d ", n);
115  }
116  LogPrint(BCLog::NET, "| ");
117 
118  LogPrint(BCLog::NET, "nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
119  }
120  }
121 }
#define strprintf
Definition: tinyformat.h:1054
Median filter over a stream of values.
Definition: timedata.h:23
int64_t GetTimeOffset()
"Never go to sea with two chronometers; take one or three." Our three time sources are: ...
Definition: timedata.cpp:30
#define PACKAGE_NAME
Definition: raven-config.h:350
#define RAVEN_TIMEDATA_MAX_SAMPLES
Definition: timedata.cpp:46
std::vector< T > sorted() const
Definition: timedata.h:68
void input(T value)
Definition: timedata.h:38
#define LOCK(cs)
Definition: sync.h:176
#define LogPrint(category,...)
Definition: util.h:160
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:32
ArgsManager gArgs
Definition: util.cpp:94
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: util.cpp:454
int64_t GetAdjustedTime()
Definition: timedata.cpp:36
void SetMiscWarning(const std::string &strWarning)
Definition: warnings.cpp:17
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:76
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units...
Definition: utiltime.cpp:20
CClientUIInterface uiInterface
Definition: ui_interface.cpp:9
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
Definition: timedata.cpp:48
int size() const
Definition: timedata.h:63
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
Definition: util.h:66
T median() const
Definition: timedata.h:50
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
Definition: sync.h:92