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