Bitcoin ABC 0.30.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 <common/args.h>
12#include <logging.h>
13#include <netaddress.h>
14#include <node/ui_interface.h>
15#include <sync.h>
16#include <util/translation.h>
17#include <warnings.h>
18
20static int64_t nTimeOffset GUARDED_BY(g_timeoffset_mutex) = 0;
21
30int64_t GetTimeOffset() {
32 return nTimeOffset;
33}
34
36 return NodeClock::now() + std::chrono::seconds{GetTimeOffset()};
37}
38
39#define BITCOIN_TIMEDATA_MAX_SAMPLES 200
40
41static std::set<CNetAddr> g_sources;
44
45void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample) {
47 // Ignore duplicates
49 return;
50 }
51 if (!g_sources.insert(ip).second) {
52 return;
53 }
54
55 // Add data
56 g_time_offsets.input(nOffsetSample);
58 "added time data, samples %d, offset %+d (%+d minutes)\n",
59 g_time_offsets.size(), nOffsetSample, nOffsetSample / 60);
60
61 // There is a known issue here (see issue #4521):
62 //
63 // - The structure g_time_offsets contains up to 200 elements, after which
64 // any new element added to it will not increase its size, replacing the
65 // oldest element.
66 //
67 // - The condition to update nTimeOffset includes checking whether the
68 // number of elements in g_time_offsets is odd, which will never happen
69 // after there are 200 elements.
70 //
71 // But in this case the 'bug' is protective against some attacks, and may
72 // actually explain why we've never seen attacks which manipulate the clock
73 // offset.
74 //
75 // So we should hold off on fixing this and clean it up as part of a timing
76 // cleanup that strengthens it in a number of other ways.
77 //
78 if (g_time_offsets.size() >= 5 && g_time_offsets.size() % 2 == 1) {
79 int64_t nMedian = g_time_offsets.median();
80 std::vector<int64_t> vSorted = g_time_offsets.sorted();
81 // Only let other nodes change our time by so much
82
83 int64_t max_adjustment =
84 std::max<int64_t>(0, gArgs.GetIntArg("-maxtimeadjustment",
86 if (nMedian >= -max_adjustment && nMedian <= max_adjustment) {
87 nTimeOffset = nMedian;
88 } else {
89 nTimeOffset = 0;
90
91 if (!g_warning_emitted) {
92 // If nobody has a time different than ours but within 5 minutes
93 // of ours, give a warning
94 bool fMatch = false;
95 for (const int64_t nOffset : vSorted) {
96 if (nOffset != 0 && nOffset > -5 * 60 && nOffset < 5 * 60) {
97 fMatch = true;
98 }
99 }
100
101 if (!fMatch) {
102 g_warning_emitted = true;
103 bilingual_str strMessage =
104 strprintf(_("Please check that your computer's date "
105 "and time are correct! If your clock is "
106 "wrong, %s will not work properly."),
107 PACKAGE_NAME);
108 SetMiscWarning(strMessage);
109 uiInterface.ThreadSafeMessageBox(
110 strMessage, "", CClientUIInterface::MSG_WARNING);
111 }
112 }
113 }
114
116 for (const int64_t n : vSorted) {
118 }
119
121 LogPrint(BCLog::NET, "nTimeOffset = %+d (%+d minutes)\n",
122 nTimeOffset, nTimeOffset / 60);
123 }
124 }
125}
126
129 nTimeOffset = 0;
130 g_sources.clear();
132 g_warning_emitted = false;
133}
ArgsManager gArgs
Definition: args.cpp:38
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
Definition: args.cpp:526
Median filter over a stream of values.
Definition: timedata.h:24
Network address.
Definition: netaddress.h:121
Different type to mark Mutex at global scope.
Definition: sync.h:144
#define LogPrint(category,...)
Definition: logging.h:238
#define LogPrintToBeContinued
Definition: logging.h:260
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
Definition: logging.h:186
@ NET
Definition: logging.h:40
static time_point now() noexcept
Return current system time or mocked time, if set.
Definition: time.cpp:71
std::chrono::time_point< NodeClock > time_point
Definition: time.h:19
Bilingual messages:
Definition: translation.h:17
#define LOCK(cs)
Definition: sync.h:306
int64_t GetTimeOffset()
"Never go to sea with two chronometers; take one or three." Our three time sources are:
Definition: timedata.cpp:30
void TestOnlyResetTimeData()
Reset the internal state of GetTimeOffset(), GetAdjustedTime() and AddTimeData().
Definition: timedata.cpp:127
static GlobalMutex g_timeoffset_mutex
Definition: timedata.cpp:19
#define BITCOIN_TIMEDATA_MAX_SAMPLES
Definition: timedata.cpp:39
NodeClock::time_point GetAdjustedTime()
Definition: timedata.cpp:35
static std::set< CNetAddr > g_sources
Definition: timedata.cpp:41
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
Definition: timedata.cpp:45
static int64_t nTimeOffset GUARDED_BY(g_timeoffset_mutex)=0
static CMedianFilter< int64_t > g_time_offsets(BITCOIN_TIMEDATA_MAX_SAMPLES, 0)
static bool g_warning_emitted
Definition: timedata.cpp:43
static const int64_t DEFAULT_MAX_TIME_ADJUSTMENT
Definition: timedata.h:16
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:68
CClientUIInterface uiInterface
void SetMiscWarning(const bilingual_str &warning)
Definition: warnings.cpp:21