cuprated/
killswitch.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//! Killswitch.
//!
//! This module implements code for shutting down `cuprated`
//! after a certain timestamp has passed.
//!
//! The reasoning is twofold:
//! 1. Limiting the effects of any network errors
//!    caused by a faulty `cuprated`.
//! 2. To enforce users to update `alpha` builds,
//!    if they choose to run them.
//!
//! This behavior is limited to an alpha build;
//! this module will be removed after a stable v1 release.

use std::{process::exit, time::Duration};

use cuprate_helper::time::current_unix_timestamp;

/// Assert that this is not a v1 release and an alpha release.
const _: () = {
    const_format::assertcp_ne!(
        crate::constants::MAJOR_VERSION,
        "1",
        "`cuprated` major version is 1, killswitch module should be deleted."
    );
};

/// The killswitch activates if the current timestamp is ahead of this timestamp.
///
/// Sat Mar 01 2025 05:00:00 GMT+0000
pub const KILLSWITCH_ACTIVATION_TIMESTAMP: u64 = 1740805200;

/// Check if the system clock is past a certain timestamp,
/// if so, exit the entire program.
fn killswitch() {
    /// A timestamp known to have been passed.
    ///
    /// This is an arbitrary timestamp used for
    /// sanity checking the system's clock to make
    /// sure it is not overly behind.
    ///
    /// Fri Jan 17 2025 14:19:10 GMT+0000
    const SYSTEM_CLOCK_SANITY_TIMESTAMP: u64 = 1737123550;

    let current_ts = current_unix_timestamp();

    // Prints a generic killswitch message.
    let print_killswitch_msg = |msg| {
        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>.");
    };

    if current_ts < SYSTEM_CLOCK_SANITY_TIMESTAMP {
        print_killswitch_msg("The system clock is too far behind and is not reliable to use");
        exit(66);
    }

    if current_ts > KILLSWITCH_ACTIVATION_TIMESTAMP {
        print_killswitch_msg("The killswitch activation timestamp for alpha builds has passed.");
        exit(88);
    }
}

/// Spawn a thread that sleeps until the [`KILLSWITCH_ACTIVATION_TIMESTAMP`] activates.
pub fn init_killswitch() {
    // Check if we should exit immediately.
    killswitch();

    // Else spawn a thread that waits until we should.
    std::thread::spawn(|| -> ! {
        // Sleep until killswitch activation.
        let current_ts = current_unix_timestamp();
        let sleep_duration = Duration::from_secs(KILLSWITCH_ACTIVATION_TIMESTAMP - current_ts);
        std::thread::sleep(sleep_duration);

        // To account for any miscalculated or drifted sleep time,
        // loop until the killswitch activates.
        loop {
            killswitch();
            std::thread::sleep(Duration::from_secs(30));
        }
    });
}