cuprated/
killswitch.rs

1//! Killswitch.
2//!
3//! This module implements code for shutting down `cuprated`
4//! after a certain timestamp has passed.
5//!
6//! The reasoning is twofold:
7//! 1. Limiting the effects of any network errors
8//!    caused by a faulty `cuprated`.
9//! 2. To enforce users to update `alpha` builds,
10//!    if they choose to run them.
11//!
12//! This behavior is limited to an alpha build;
13//! this module will be removed after a stable v1 release.
14
15use std::{process::exit, time::Duration};
16
17use cuprate_helper::time::current_unix_timestamp;
18
19/// Assert that this is an alpha release.
20const _: () = {
21    const_format::assertcp_ne!(
22        crate::constants::MAJOR_VERSION,
23        "1",
24        "`cuprated` major version is 1, killswitch module should be deleted."
25    );
26    const_format::assertcp_ne!(
27        crate::constants::MINOR_VERSION,
28        "1",
29        "`cuprated` minor version is 1, killswitch module should be deleted."
30    );
31};
32
33/// The killswitch activates if the current timestamp is ahead of this timestamp.
34///
35/// Wed Apr 16 12:00:00 AM UTC 2025
36pub const KILLSWITCH_ACTIVATION_TIMESTAMP: u64 = 1744761600;
37
38/// Check if the system clock is past a certain timestamp,
39/// if so, exit the entire program.
40fn killswitch() {
41    /// A timestamp known to have been passed.
42    ///
43    /// This is an arbitrary timestamp used for
44    /// sanity checking the system's clock to make
45    /// sure it is not overly behind.
46    ///
47    /// Tue Mar 11 08:33:20 PM UTC 2025
48    const SYSTEM_CLOCK_SANITY_TIMESTAMP: u64 = 1741725200;
49
50    let current_ts = current_unix_timestamp();
51
52    // Prints a generic killswitch message.
53    let print_killswitch_msg = |msg| {
54        eprintln!("killswitch: {msg}. (current_ts: {current_ts}, killswitch_activation_timestamp: {KILLSWITCH_ACTIVATION_TIMESTAMP}). `cuprated` will now exit. For more details on why this exists, see: <https://github.com/Cuprate/cuprate/pull/365>.");
55    };
56
57    if current_ts < SYSTEM_CLOCK_SANITY_TIMESTAMP {
58        print_killswitch_msg("The system clock is too far behind and is not reliable to use");
59        exit(66);
60    }
61
62    if current_ts > KILLSWITCH_ACTIVATION_TIMESTAMP {
63        print_killswitch_msg("The killswitch activation timestamp for alpha builds has passed.");
64        exit(88);
65    }
66}
67
68/// Spawn a thread that sleeps until the [`KILLSWITCH_ACTIVATION_TIMESTAMP`] activates.
69pub fn init_killswitch() {
70    // Check if we should exit immediately.
71    killswitch();
72
73    // Else spawn a thread that waits until we should.
74    std::thread::spawn(|| -> ! {
75        // Sleep until killswitch activation.
76        let current_ts = current_unix_timestamp();
77        let sleep_duration = Duration::from_secs(KILLSWITCH_ACTIVATION_TIMESTAMP - current_ts);
78        std::thread::sleep(sleep_duration);
79
80        // To account for any miscalculated or drifted sleep time,
81        // loop until the killswitch activates.
82        loop {
83            killswitch();
84            std::thread::sleep(Duration::from_secs(30));
85        }
86    });
87}