PRCYCoin  2.0.0.7rc1
P2P Digital Currency
timedata.cpp
Go to the documentation of this file.
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.
4 
5 #include "timedata.h"
6 
7 #include "netaddress.h"
8 #include "sync.h"
9 #include "guiinterface.h"
10 #include "util.h"
11 #include "utilstrencodings.h"
12 
13 
14 static RecursiveMutex cs_nTimeOffset;
15 static int64_t nTimeOffset = 0;
16 
24 int64_t GetTimeOffset()
25 {
26  LOCK(cs_nTimeOffset);
27  return nTimeOffset;
28 }
29 
30 int64_t GetAdjustedTime()
31 {
32  return GetTime() + GetTimeOffset();
33 }
34 
35 static int64_t abs64(int64_t n)
36 {
37  return (n >= 0 ? n : -n);
38 }
39 
40 void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
41 {
42  LOCK(cs_nTimeOffset);
43  // Ignore duplicates
44  static std::set<CNetAddr> setKnown;
45  if (!setKnown.insert(ip).second)
46  return;
47 
48  // Add data
49  static CMedianFilter<int64_t> vTimeOffsets(200, 0);
50  vTimeOffsets.input(nOffsetSample);
51  LogPrintf("Added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample / 60);
52 
53  // There is a known issue here (see issue #4521):
54  //
55  // - The structure vTimeOffsets contains up to 200 elements, after which
56  // any new element added to it will not increase its size, replacing the
57  // oldest element.
58  //
59  // - The condition to update nTimeOffset includes checking whether the
60  // number of elements in vTimeOffsets is odd, which will never happen after
61  // there are 200 elements.
62  //
63  // But in this case the 'bug' is protective against some attacks, and may
64  // actually explain why we've never seen attacks which manipulate the
65  // clock offset.
66  //
67  // So we should hold off on fixing this and clean it up as part of
68  // a timing cleanup that strengthens it in a number of other ways.
69  //
70  if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) {
71  int64_t nMedian = vTimeOffsets.median();
72  std::vector<int64_t> vSorted = vTimeOffsets.sorted();
73  // Only let other nodes change our time by so much
74  if (abs64(nMedian) < 70 * 60) {
75  nTimeOffset = nMedian;
76  } else {
77  nTimeOffset = 0;
78 
79  static bool fDone;
80  if (!fDone) {
81  // If nobody has a time different than ours but within 5 minutes of ours, give a warning
82  bool fMatch = false;
83  for (int64_t nOffset : vSorted)
84  if (nOffset != 0 && abs64(nOffset) < 5 * 60)
85  fMatch = true;
86 
87  if (!fMatch) {
88  fDone = true;
89  std::string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong PRCY will not work properly.");
90  strMiscWarning = strMessage;
91  LogPrintf("*** %s\n", strMessage);
93  }
94  }
95  }
96  if (!GetBoolArg("-shrinkdebugfile", g_logger->DefaultShrinkDebugFile())) {
97  for (int64_t n : vSorted)
98  LogPrintf("%+d ", n);
99  LogPrintf("| ");
100  }
101  LogPrintf("nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset / 60);
102  }
103 }
CMedianFilter
Median filter over a stream of values.
Definition: timedata.h:20
GetTime
int64_t GetTime()
For unit testing.
Definition: utiltime.cpp:19
sync.h
timedata.h
uiInterface
CClientUIInterface uiInterface
Definition: init.cpp:101
CNetAddr
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:30
g_logger
BCLog::Logger *const g_logger
NOTE: the logger instances is leaked on exit.
Definition: logging.cpp:28
strMiscWarning
std::string strMiscWarning
Definition: util.cpp:115
AnnotatedMixin< std::recursive_mutex >
guiinterface.h
CMedianFilter::median
T median() const
Definition: timedata.h:47
_
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result.
Definition: guiinterface.h:119
CClientUIInterface::ThreadSafeMessageBox
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: guiinterface.h:80
netaddress.h
CClientUIInterface::MSG_WARNING
@ MSG_WARNING
Definition: guiinterface.h:75
GetBoolArg
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
Definition: util.cpp:255
LogPrintf
#define LogPrintf(...)
Definition: logging.h:147
CMedianFilter::size
int size() const
Definition: timedata.h:60
AddTimeData
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
Definition: timedata.cpp:40
GetAdjustedTime
int64_t GetAdjustedTime()
Definition: timedata.cpp:30
BCLog::Logger::DefaultShrinkDebugFile
bool DefaultShrinkDebugFile() const
Definition: logging.cpp:89
LOCK
#define LOCK(cs)
Definition: sync.h:182
CMedianFilter::input
void input(T value)
Definition: timedata.h:35
utilstrencodings.h
GetTimeOffset
int64_t GetTimeOffset()
"Never go to sea with two chronometers; take one or three." Our three time sources are:
Definition: timedata.cpp:24
util.h
CMedianFilter::sorted
std::vector< T > sorted() const
Definition: timedata.h:65