Bitcoin ABC  0.24.7
P2P Digital Currency
timedata.cpp
Go to the documentation of this file.
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.
4 
5 #if defined(HAVE_CONFIG_H)
6 #include <config/bitcoin-config.h>
7 #endif
8 
9 #include <timedata.h>
10 
11 #include <netaddress.h>
12 #include <node/ui_interface.h>
13 #include <sync.h>
14 #include <util/system.h>
15 #include <util/translation.h>
16 #include <warnings.h>
17 
19 static int64_t nTimeOffset GUARDED_BY(g_timeoffset_mutex) = 0;
20 
29 int64_t GetTimeOffset() {
31  return nTimeOffset;
32 }
33 
34 int64_t GetAdjustedTime() {
35  return GetTime() + GetTimeOffset();
36 }
37 
38 #define BITCOIN_TIMEDATA_MAX_SAMPLES 200
39 
40 void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample) {
42  // Ignore duplicates
43  static std::set<CNetAddr> setKnown;
44  if (setKnown.size() == BITCOIN_TIMEDATA_MAX_SAMPLES) {
45  return;
46  }
47  if (!setKnown.insert(ip).second) {
48  return;
49  }
50 
51  // Add data
53  vTimeOffsets.input(nOffsetSample);
55  "added time data, samples %d, offset %+d (%+d minutes)\n",
56  vTimeOffsets.size(), nOffsetSample, nOffsetSample / 60);
57 
58  // There is a known issue here (see issue #4521):
59  //
60  // - The structure vTimeOffsets contains up to 200 elements, after which any
61  // new element added to it will not increase its size, replacing the oldest
62  // element.
63  //
64  // - The condition to update nTimeOffset includes checking whether the
65  // number of elements in vTimeOffsets is odd, which will never happen after
66  // there are 200 elements.
67  //
68  // But in this case the 'bug' is protective against some attacks, and may
69  // actually explain why we've never seen attacks which manipulate the clock
70  // offset.
71  //
72  // So we should hold off on fixing this and clean it up as part of a timing
73  // cleanup that strengthens it in a number of other ways.
74  //
75  if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) {
76  int64_t nMedian = vTimeOffsets.median();
77  std::vector<int64_t> vSorted = vTimeOffsets.sorted();
78  // Only let other nodes change our time by so much
79 
80  int64_t max_adjustment = std::max<int64_t>(
81  0, gArgs.GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT));
82  if (nMedian >= -max_adjustment && nMedian <= max_adjustment) {
83  nTimeOffset = nMedian;
84  } else {
85  nTimeOffset = 0;
86 
87  static bool fDone;
88  if (!fDone) {
89  // If nobody has a time different than ours but within 5 minutes
90  // of ours, give a warning
91  bool fMatch = false;
92  for (const int64_t nOffset : vSorted) {
93  if (nOffset != 0 && nOffset > -5 * 60 && nOffset < 5 * 60) {
94  fMatch = true;
95  }
96  }
97 
98  if (!fMatch) {
99  fDone = true;
100  bilingual_str strMessage =
101  strprintf(_("Please check that your computer's date "
102  "and time are correct! If your clock is "
103  "wrong, %s will not work properly."),
104  PACKAGE_NAME);
105  SetMiscWarning(strMessage);
106  uiInterface.ThreadSafeMessageBox(
107  strMessage, "", CClientUIInterface::MSG_WARNING);
108  }
109  }
110  }
111 
113  for (const int64_t n : vSorted) {
114  LogPrintToBeContinued(BCLog::NET, "%+d ", n);
115  }
116 
118  LogPrint(BCLog::NET, "nTimeOffset = %+d (%+d minutes)\n",
119  nTimeOffset, nTimeOffset / 60);
120  }
121  }
122 }
CMedianFilter
Median filter over a stream of values.
Definition: timedata.h:21
_
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:55
DEFAULT_MAX_TIME_ADJUSTMENT
static const int64_t DEFAULT_MAX_TIME_ADJUSTMENT
Definition: timedata.h:13
uiInterface
CClientUIInterface uiInterface
Definition: ui_interface.cpp:12
sync.h
timedata.h
bilingual_str
Bilingual messages:
Definition: translation.h:17
CNetAddr
Network address.
Definition: netaddress.h:117
GetTime
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
Definition: time.cpp:27
AnnotatedMixin< std::mutex >
CMedianFilter::median
T median() const
Definition: timedata.h:45
g_timeoffset_mutex
static Mutex g_timeoffset_mutex
Definition: timedata.cpp:18
GUARDED_BY
static int64_t nTimeOffset GUARDED_BY(g_timeoffset_mutex)=0
netaddress.h
CClientUIInterface::MSG_WARNING
@ MSG_WARNING
Definition: ui_interface.h:72
SetMiscWarning
void SetMiscWarning(const bilingual_str &warning)
Definition: warnings.cpp:21
ArgsManager::GetArg
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:498
LogPrint
#define LogPrint(category,...)
Definition: logging.h:193
LogPrintToBeContinued
#define LogPrintToBeContinued
Definition: logging.h:206
CMedianFilter::size
int size() const
Definition: timedata.h:59
AddTimeData
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
Definition: timedata.cpp:40
ui_interface.h
system.h
strprintf
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1201
GetAdjustedTime
int64_t GetAdjustedTime()
Definition: timedata.cpp:34
LogAcceptCategory
static bool LogAcceptCategory(BCLog::LogFlags category)
Return true if log accepts specified category.
Definition: logging.h:164
translation.h
LOCK
#define LOCK(cs)
Definition: sync.h:241
gArgs
ArgsManager gArgs
Definition: system.cpp:75
BITCOIN_TIMEDATA_MAX_SAMPLES
#define BITCOIN_TIMEDATA_MAX_SAMPLES
Definition: timedata.cpp:38
CMedianFilter::input
void input(T value)
Definition: timedata.h:34
BCLog::NET
@ NET
Definition: logging.h:38
GetTimeOffset
int64_t GetTimeOffset()
"Never go to sea with two chronometers; take one or three." Our three time sources are:
Definition: timedata.cpp:29
warnings.h
CMedianFilter::sorted
std::vector< T > sorted() const
Definition: timedata.h:61