zebrad/components/sync/
end_of_support.rs

1//! End of support checking task.
2
3use std::time::Duration;
4
5use color_eyre::Report;
6
7use zebra_chain::{
8    block::Height,
9    chain_tip::ChainTip,
10    parameters::{Network, NetworkUpgrade},
11};
12
13use crate::application::release_version;
14
15/// The estimated height that this release will be published.
16pub const ESTIMATED_RELEASE_HEIGHT: u32 = 2_809_400;
17
18/// The maximum number of days after `ESTIMATED_RELEASE_HEIGHT` where a Zebra server will run
19/// without halting.
20///
21/// Notes:
22///
23/// - Zebra will exit with a panic if the current tip height is bigger than the
24///   `ESTIMATED_RELEASE_HEIGHT` plus this number of days.
25/// - Currently set to 16 weeks.
26pub const EOS_PANIC_AFTER: u32 = 112;
27
28/// The number of days before the end of support where Zebra will display warnings.
29pub const EOS_WARN_AFTER: u32 = EOS_PANIC_AFTER - 14;
30
31/// A string which is part of the panic that will be displayed if Zebra halts.
32pub const EOS_PANIC_MESSAGE_HEADER: &str = "Zebra refuses to run";
33
34/// A string which is part of the warning that will be displayed if Zebra release is close to halting.
35pub const EOS_WARN_MESSAGE_HEADER: &str = "Your Zebra release is too old and it will stop running";
36
37/// The amount of time between end of support checks.
38const CHECK_INTERVAL: Duration = Duration::from_secs(60 * 60);
39
40/// Wait a few seconds at startup so `best_tip_height` is always `Some`.
41const INITIAL_WAIT: Duration = Duration::from_secs(10);
42
43/// Start the end of support checking task for Mainnet.
44pub async fn start(
45    network: Network,
46    latest_chain_tip: impl ChainTip + std::fmt::Debug,
47) -> Result<(), Report> {
48    info!("Starting end of support task");
49
50    tokio::time::sleep(INITIAL_WAIT).await;
51
52    loop {
53        if network == Network::Mainnet {
54            if let Some(tip_height) = latest_chain_tip.best_tip_height() {
55                check(tip_height, &network);
56            }
57        } else {
58            info!("Release always valid in Testnet");
59        }
60        tokio::time::sleep(CHECK_INTERVAL).await;
61    }
62}
63
64/// Check if the current release is too old and panic if so.
65pub fn check(tip_height: Height, network: &Network) {
66    info!("Checking if Zebra release is inside support range ...");
67
68    // Get the current block spacing
69    let target_block_spacing = NetworkUpgrade::target_spacing_for_height(network, tip_height);
70
71    // Get the number of blocks per day
72    let estimated_blocks_per_day =
73        u32::try_from(chrono::Duration::days(1).num_seconds() / target_block_spacing.num_seconds())
74            .expect("number is always small enough to fit");
75
76    let panic_height =
77        Height(ESTIMATED_RELEASE_HEIGHT + (EOS_PANIC_AFTER * estimated_blocks_per_day));
78    let warn_height =
79        Height(ESTIMATED_RELEASE_HEIGHT + (EOS_WARN_AFTER * estimated_blocks_per_day));
80
81    if tip_height > panic_height {
82        panic!(
83            "{EOS_PANIC_MESSAGE_HEADER} if the release date is older than {EOS_PANIC_AFTER} days. \
84            \nRelease name: {}, Estimated release height: {ESTIMATED_RELEASE_HEIGHT} \
85            \nHint: Download and install the latest Zebra release from: https://github.com/ZcashFoundation/zebra/releases/latest",
86            release_version()
87        );
88    } else if tip_height > warn_height {
89        warn!(
90            "{EOS_WARN_MESSAGE_HEADER} at block {}. \
91            \nRelease name: {}, Estimated release height: {ESTIMATED_RELEASE_HEIGHT} \
92            \nHint: Download and install the latest Zebra release from: https://github.com/ZcashFoundation/zebra/releases/latest", panic_height.0, release_version()
93        );
94    } else {
95        info!("Zebra release is supported until block {}, please report bugs at https://github.com/ZcashFoundation/zebra/issues", panic_height.0);
96    }
97}