Bitcoin Core  27.99.0
P2P Digital Currency
timeoffsets.cpp
Go to the documentation of this file.
1 // Copyright (c) 2024-present 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 <logging.h>
6 #include <node/interface_ui.h>
7 #include <node/timeoffsets.h>
8 #include <sync.h>
9 #include <tinyformat.h>
10 #include <util/time.h>
11 #include <util/translation.h>
12 #include <warnings.h>
13 
14 #include <algorithm>
15 #include <chrono>
16 #include <cstdint>
17 #include <deque>
18 #include <limits>
19 #include <optional>
20 
21 using namespace std::chrono_literals;
22 
23 void TimeOffsets::Add(std::chrono::seconds offset)
24 {
25  LOCK(m_mutex);
26 
27  if (m_offsets.size() >= MAX_SIZE) {
28  m_offsets.pop_front();
29  }
30  m_offsets.push_back(offset);
31  LogDebug(BCLog::NET, "Added time offset %+ds, total samples %d\n",
32  Ticks<std::chrono::seconds>(offset), m_offsets.size());
33 }
34 
35 std::chrono::seconds TimeOffsets::Median() const
36 {
37  LOCK(m_mutex);
38 
39  // Only calculate the median if we have 5 or more offsets
40  if (m_offsets.size() < 5) return 0s;
41 
42  auto sorted_copy = m_offsets;
43  std::sort(sorted_copy.begin(), sorted_copy.end());
44  return sorted_copy[sorted_copy.size() / 2]; // approximate median is good enough, keep it simple
45 }
46 
48 {
49  // when median == std::numeric_limits<int64_t>::min(), calling std::chrono::abs is UB
50  auto median{std::max(Median(), std::chrono::seconds(std::numeric_limits<int64_t>::min() + 1))};
51  if (std::chrono::abs(median) <= WARN_THRESHOLD) {
52  SetMedianTimeOffsetWarning(std::nullopt);
53  uiInterface.NotifyAlertChanged();
54  return false;
55  }
56 
58  "Your computer's date and time appear to be more than %d minutes out of sync with the network, "
59  "this may lead to consensus failure. After you've confirmed your computer's clock, this message "
60  "should no longer appear when you restart your node. Without a restart, it should stop showing "
61  "automatically after you've connected to a sufficient number of new outbound peers, which may "
62  "take some time. You can inspect the `timeoffset` field of the `getpeerinfo` and `getnetworkinfo` "
63  "RPC methods to get more info."
64  ), Ticks<std::chrono::minutes>(WARN_THRESHOLD))};
65  LogWarning("%s\n", msg.original);
67  uiInterface.NotifyAlertChanged();
68  return true;
69 }
void Add(std::chrono::seconds offset) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a new time offset sample.
Definition: timeoffsets.cpp:23
bool WarnIfOutOfSync() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Raise warnings if the median time offset exceeds the warnings threshold.
Definition: timeoffsets.cpp:47
std::chrono::seconds Median() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Compute and return the median of the collected time offset samples.
Definition: timeoffsets.cpp:35
CClientUIInterface uiInterface
#define LogWarning(...)
Definition: logging.h:240
#define LogDebug(category,...)
Definition: logging.h:259
@ NET
Definition: logging.h:41
static constexpr uint64_t MAX_SIZE
The maximum size of a serialized object in bytes or number of elements (for eg vectors) when the size...
Definition: serialize.h:32
Bilingual messages:
Definition: translation.h:18
#define LOCK(cs)
Definition: sync.h:257
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1162
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:74
void SetMedianTimeOffsetWarning(std::optional< bilingual_str > warning)
Pass std::nullopt to disable the warning.
Definition: warnings.cpp:34