/Users/eugenesiegel/btc/bitcoin/src/node/timeoffsets.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | void TimeOffsets::Add(std::chrono::seconds offset) |
23 | 46.7k | { |
24 | 46.7k | LOCK(m_mutex); Line | Count | Source | 257 | 46.7k | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 46.7k | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 46.7k | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 46.7k | #define PASTE(x, y) x ## y |
|
|
|
|
25 | | |
26 | 46.7k | if (m_offsets.size() >= MAX_SIZE) { |
27 | 0 | m_offsets.pop_front(); |
28 | 0 | } |
29 | 46.7k | m_offsets.push_back(offset); |
30 | 46.7k | LogDebug(BCLog::NET, "Added time offset %+ds, total samples %d\n", Line | Count | Source | 280 | 46.7k | #define LogDebug(category, ...) LogPrintLevel(category, BCLog::Level::Debug, __VA_ARGS__) Line | Count | Source | 273 | 46.7k | do { \ | 274 | 46.7k | if (LogAcceptCategory((category), (level))) { \ | 275 | 0 | LogPrintLevel_(category, level, __VA_ARGS__); \ Line | Count | Source | 255 | 0 | #define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__) |
| 276 | 0 | } \ | 277 | 46.7k | } while (0) |
|
|
31 | 46.7k | Ticks<std::chrono::seconds>(offset), m_offsets.size()); |
32 | 46.7k | } |
33 | | |
34 | | std::chrono::seconds TimeOffsets::Median() const |
35 | 46.7k | { |
36 | 46.7k | LOCK(m_mutex); Line | Count | Source | 257 | 46.7k | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) Line | Count | Source | 11 | 46.7k | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) Line | Count | Source | 9 | 46.7k | #define PASTE2(x, y) PASTE(x, y) Line | Count | Source | 8 | 46.7k | #define PASTE(x, y) x ## y |
|
|
|
|
37 | | |
38 | | // Only calculate the median if we have 5 or more offsets |
39 | 46.7k | if (m_offsets.size() < 5) return 0s; |
40 | | |
41 | 0 | auto sorted_copy = m_offsets; |
42 | 0 | std::sort(sorted_copy.begin(), sorted_copy.end()); |
43 | 0 | return sorted_copy[sorted_copy.size() / 2]; // approximate median is good enough, keep it simple |
44 | 46.7k | } |
45 | | |
46 | | bool TimeOffsets::WarnIfOutOfSync() const |
47 | 46.7k | { |
48 | | // when median == std::numeric_limits<int64_t>::min(), calling std::chrono::abs is UB |
49 | 46.7k | auto median{std::max(Median(), std::chrono::seconds(std::numeric_limits<int64_t>::min() + 1))}; |
50 | 46.7k | if (std::chrono::abs(median) <= WARN_THRESHOLD) { |
51 | 46.7k | m_warnings.Unset(node::Warning::CLOCK_OUT_OF_SYNC); |
52 | 46.7k | return false; |
53 | 46.7k | } |
54 | | |
55 | 0 | bilingual_str msg{strprintf(_( Line | Count | Source | 1172 | 0 | #define strprintf tfm::format |
|
56 | 0 | "Your computer's date and time appear to be more than %d minutes out of sync with the network, " |
57 | 0 | "this may lead to consensus failure. After you've confirmed your computer's clock, this message " |
58 | 0 | "should no longer appear when you restart your node. Without a restart, it should stop showing " |
59 | 0 | "automatically after you've connected to a sufficient number of new outbound peers, which may " |
60 | 0 | "take some time. You can inspect the `timeoffset` field of the `getpeerinfo` and `getnetworkinfo` " |
61 | 0 | "RPC methods to get more info." |
62 | 0 | ), Ticks<std::chrono::minutes>(WARN_THRESHOLD))}; |
63 | 0 | LogWarning("%s\n", msg.original); Line | Count | Source | 262 | 0 | #define LogWarning(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Warning, __VA_ARGS__) Line | Count | Source | 255 | 0 | #define LogPrintLevel_(category, level, ...) LogPrintFormatInternal(__func__, __FILE__, __LINE__, category, level, __VA_ARGS__) |
|
|
64 | 0 | m_warnings.Set(node::Warning::CLOCK_OUT_OF_SYNC, msg); |
65 | 0 | return true; |
66 | 46.7k | } |