Skip to content

Loud clock-drift warnings + NTP offset window flush + GetInfo time fields - #99

Open
moralpriest wants to merge 6 commits into
DEROFDN:community-devfrom
moralpriest:feat/loud-clock-warnings
Open

Loud clock-drift warnings + NTP offset window flush + GetInfo time fields#99
moralpriest wants to merge 6 commits into
DEROFDN:community-devfrom
moralpriest:feat/loud-clock-warnings

Conversation

@moralpriest

Copy link
Copy Markdown

Summary

--timeisinsync semantics are unchanged. This patch only makes clock problems visible and fixes the reporting pipeline around them:

  1. Loud, once-per-transition warnings (p2p/timecheck.go): CLOCK DRIFT and Cannot-reach-NTP now log at default verbosity (previously V(1) — invisible without --debug). Re-warns are gated: drift by state change; unreachable by a 10-minute cooldown so intermittent connectivity doesn't nag every minute.
  2. Startup probe: synchronous NTP check in P2P_Init prints drift within seconds of launch instead of minutes.
  3. Offset-window flush on recovery (fixes real staleness bug): the 128-sample rolling average kept applying a multi-minute correction for hours after chrony had already fixed the OS clock (in-sync poll is 60-120s). On the drift→sync transition we flush stale samples and seed the average from the live reading, so globals.Time() and GetInfo converge immediately.
  4. Large-offset bypass of Validate(): beevik/ntp Validate() (freshness/dispersion) can reject a response that still carries a clearly-drifted offset (seen with flaky RTT); if |offset| > 1s we report drift rather than pretending the query failed.
  5. OS-specific hints: Windows (w32tm / Settings), macOS (Date & Time), Linux (timedatectl set-ntp true, chrony) instead of Linux-only advice on every platform.
  6. GetInfo additions (backward-compatible): clock_offset_ntp_ms, clock_offset_p2p_ms, time_in_sync — lets node managers/explorers read the daemon's own measurement remotely.

Test evidence

  • Unit tests: once-per-transition emission, cooldown expiry, success-does-not-re-arm, offsetWindow avg/flush/wrap-around, GOOS hint pins (go test ./p2p ./rpc ./globals green).
  • Cross-compile: windows/amd64 + darwin/amd64 build clean.
  • Live manual tests on testnet (Linux host):
    • date -s '+2 minutes' → single CLOCK DRIFT banner at default level; GetInfo shows -120001 ms / time_in_sync:false.
    • Flag off vs on while skewed: prompt/status show daemon applies −2m correction without flag, ~0 with --timeisinsync; warning fires either way.
    • Restore NTP → one "back in sync" line and GetInfo flips to ~0/true immediately (window flush).
    • iptables UDP/123 drop → exactly one unreachable line carrying the real socket error.

Compatibility

No changes to consensus logic, flag parsing, or defaults. New GetInfo fields are additive JSON.

- p2p/timecheck: emit CLOCK DRIFT and NTP-unreachable at default log level, once per state change (no --debug needed)
- probeClockOnce() runs a synchronous NTP check at P2P_Init so startup prints immediately
- --timeisinsync flag unchanged (still disables NTP correction)
- GetInfo adds clock_offset_ntp_ms, clock_offset_p2p_ms, time_in_sync
- unit tests for once-per-transition reporting
libfaketime and messy RTT trip beevik/ntp Validate() (freshness/dispersion),
which we were logging as "Cannot reach NTP". If Query returns a |offset| > 1s,
report CLOCK DRIFT instead. Unreachable warnings now include the query error.
derod is one binary per GOOS — print Windows (w32tm / Settings),
macOS (Date & Time), or Linux (timedatectl/chrony) instead of
Linux-only chrony/timedatectl on every platform.
A 128-sample rolling average kept reporting multi-minute drift for hours
after chrony had already stepped the OS clock (in-sync poll is 60-120s).
On the drift→sync transition, drop stale samples and seed the average
from the live reading so GetInfo/Time() converge immediately.
With intermittent connectivity, successes reset the warn latch and each
new failure re-warned — a nag every minute. Gate re-warnings solely on
time since the last warning (10 min); successes no longer re-arm it.
probeClockOnce now reports the real query error too.
Fill all 128 slots then overwrite the oldest; avg must stay exact.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant