Dash Core  0.12.2.1
P2P Digital Currency
timedata.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2015 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 #include "timedata.h"
6 
7 #include "netaddress.h"
8 #include "sync.h"
9 #include "ui_interface.h"
10 #include "util.h"
11 #include "utilstrencodings.h"
12 
13 #include <boost/foreach.hpp>
14 
15 using namespace std;
16 
18 static int64_t nTimeOffset = 0;
19 
27 int64_t GetTimeOffset()
28 {
30  return nTimeOffset;
31 }
32 
33 int64_t GetAdjustedTime()
34 {
35  return GetTime() + GetTimeOffset();
36 }
37 
38 static int64_t abs64(int64_t n)
39 {
40  return (n >= 0 ? n : -n);
41 }
42 
43 #define BITCOIN_TIMEDATA_MAX_SAMPLES 200
44 
45 void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
46 {
48  // Ignore duplicates
49  static set<CNetAddr> setKnown;
50  if (setKnown.size() == BITCOIN_TIMEDATA_MAX_SAMPLES)
51  return;
52  if (!setKnown.insert(ip).second)
53  return;
54 
55  // Add data
57  vTimeOffsets.input(nOffsetSample);
58  LogPrint("net","added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
59 
60  // There is a known issue here (see issue #4521):
61  //
62  // - The structure vTimeOffsets contains up to 200 elements, after which
63  // any new element added to it will not increase its size, replacing the
64  // oldest element.
65  //
66  // - The condition to update nTimeOffset includes checking whether the
67  // number of elements in vTimeOffsets is odd, which will never happen after
68  // there are 200 elements.
69  //
70  // But in this case the 'bug' is protective against some attacks, and may
71  // actually explain why we've never seen attacks which manipulate the
72  // clock offset.
73  //
74  // So we should hold off on fixing this and clean it up as part of
75  // a timing cleanup that strengthens it in a number of other ways.
76  //
77  if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
78  {
79  int64_t nMedian = vTimeOffsets.median();
80  std::vector<int64_t> vSorted = vTimeOffsets.sorted();
81  // Only let other nodes change our time by so much
82  if (abs64(nMedian) < 70 * 60)
83  {
84  nTimeOffset = nMedian;
85  }
86  else
87  {
88  nTimeOffset = 0;
89 
90  static bool fDone;
91  if (!fDone)
92  {
93  // If nobody has a time different than ours but within 5 minutes of ours, give a warning
94  bool fMatch = false;
95  BOOST_FOREACH(int64_t nOffset, vSorted)
96  if (nOffset != 0 && abs64(nOffset) < 5 * 60)
97  fMatch = true;
98 
99  if (!fMatch)
100  {
101  fDone = true;
102  string strMessage = _("Please check that your computer's date and time are correct! If your clock is wrong Dash Core will not work properly.");
103  strMiscWarning = strMessage;
105  }
106  }
107  }
108 
109  BOOST_FOREACH(int64_t n, vSorted)
110  LogPrint("net", "%+d ", n);
111  LogPrint("net", "| ");
112 
113  LogPrint("net", "nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60);
114  }
115 }
static CCriticalSection cs_nTimeOffset
Definition: timedata.cpp:17
string strMiscWarning
Definition: util.cpp:129
#define BITCOIN_TIMEDATA_MAX_SAMPLES
Definition: timedata.cpp:43
static int64_t abs64(int64_t n)
Definition: timedata.cpp:38
int size() const
Definition: timedata.h:60
T median() const
Definition: timedata.h:47
static int64_t nTimeOffset
Definition: timedata.cpp:18
int64_t GetTimeOffset()
Definition: timedata.cpp:27
boost::signals2::signal< bool(const std::string &message, const std::string &caption, unsigned int style), boost::signals2::last_value< bool > > ThreadSafeMessageBox
Definition: ui_interface.h:77
void input(T value)
Definition: timedata.h:35
static int LogPrint(const char *category, const char *format)
Definition: util.h:126
#define LOCK(cs)
Definition: sync.h:168
CClientUIInterface uiInterface
Definition: init.cpp:130
std::vector< T > sorted() const
Definition: timedata.h:65
int64_t GetAdjustedTime()
Definition: timedata.cpp:33
int64_t GetTime()
For unit testing.
Definition: utiltime.cpp:20
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
Definition: timedata.cpp:45
std::string _(const char *psz)
Definition: util.h:84