Branch data Line data Source code
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/timeoffsets.h>
7 : : #include <node/warnings.h>
8 : : #include <sync.h>
9 : : #include <tinyformat.h>
10 : : #include <util/time.h>
11 : : #include <util/translation.h>
12 : :
13 : : #include <algorithm>
14 : : #include <chrono>
15 : : #include <cstdint>
16 : : #include <deque>
17 : : #include <limits>
18 : : #include <optional>
19 : :
20 : : using namespace std::chrono_literals;
21 : :
22 : 728 : void TimeOffsets::Add(std::chrono::seconds offset)
23 : : {
24 : 728 : LOCK(m_mutex);
25 : :
26 [ + + ]: 728 : if (m_offsets.size() >= MAX_SIZE) {
27 : 75 : m_offsets.pop_front();
28 : : }
29 [ + - ]: 728 : m_offsets.push_back(offset);
30 [ + - + - : 728 : LogDebug(BCLog::NET, "Added time offset %+ds, total samples %d\n",
+ - + - ]
31 : : Ticks<std::chrono::seconds>(offset), m_offsets.size());
32 : 728 : }
33 : :
34 : 1514 : std::chrono::seconds TimeOffsets::Median() const
35 : : {
36 : 1514 : LOCK(m_mutex);
37 : :
38 : : // Only calculate the median if we have 5 or more offsets
39 [ + + ]: 1514 : if (m_offsets.size() < 5) return 0s;
40 : :
41 [ + - ]: 166 : auto sorted_copy = m_offsets;
42 : 166 : std::sort(sorted_copy.begin(), sorted_copy.end());
43 : 166 : return sorted_copy[sorted_copy.size() / 2]; // approximate median is good enough, keep it simple
44 : 1680 : }
45 : :
46 : 543 : bool TimeOffsets::WarnIfOutOfSync() const
47 : : {
48 : : // when median == std::numeric_limits<int64_t>::min(), calling std::chrono::abs is UB
49 : 543 : auto median{std::max(Median(), std::chrono::seconds(std::numeric_limits<int64_t>::min() + 1))};
50 [ + + ]: 543 : if (std::chrono::abs(median) <= WARN_THRESHOLD) {
51 : 532 : m_warnings.Unset(node::Warning::CLOCK_OUT_OF_SYNC);
52 : 532 : return false;
53 : : }
54 : :
55 : 0 : bilingual_str msg{strprintf(_(
56 : : "Your computer's date and time appear to be more than %d minutes out of sync with the network, "
57 : : "this may lead to consensus failure. After you've confirmed your computer's clock, this message "
58 : : "should no longer appear when you restart your node. Without a restart, it should stop showing "
59 : : "automatically after you've connected to a sufficient number of new outbound peers, which may "
60 : : "take some time. You can inspect the `timeoffset` field of the `getpeerinfo` and `getnetworkinfo` "
61 : : "RPC methods to get more info."
62 [ + - ]: 11 : ), Ticks<std::chrono::minutes>(WARN_THRESHOLD))};
63 [ + - ]: 11 : LogWarning("%s\n", msg.original);
64 [ + - + - ]: 11 : m_warnings.Set(node::Warning::CLOCK_OUT_OF_SYNC, msg);
65 : 11 : return true;
66 : 11 : }
|