1use snarkos_node_router::{Routing, messages::NodeType};
17use snarkvm::prelude::{Address, Network, PrivateKey, ViewKey};
18
19use once_cell::sync::OnceCell;
20use std::{
21 future::Future,
22 io,
23 sync::{
24 Arc,
25 atomic::{AtomicBool, Ordering},
26 },
27 time::Duration,
28};
29
30#[async_trait]
31pub trait NodeInterface<N: Network>: Routing<N> {
32 fn node_type(&self) -> NodeType {
34 self.router().node_type()
35 }
36
37 fn private_key(&self) -> &PrivateKey<N> {
39 self.router().private_key()
40 }
41
42 fn view_key(&self) -> &ViewKey<N> {
44 self.router().view_key()
45 }
46
47 fn address(&self) -> Address<N> {
49 self.router().address()
50 }
51
52 fn is_dev(&self) -> bool {
54 self.router().is_dev()
55 }
56
57 fn handle_signals(shutdown_flag: Arc<AtomicBool>) -> Arc<OnceCell<Self>> {
60 let node: Arc<OnceCell<Self>> = Default::default();
63
64 #[cfg(target_family = "unix")]
65 fn signal_listener() -> impl Future<Output = io::Result<()>> {
66 use tokio::signal::unix::{SignalKind, signal};
67
68 let mut s_int = signal(SignalKind::interrupt()).unwrap();
70 let mut s_term = signal(SignalKind::terminate()).unwrap();
71 let mut s_quit = signal(SignalKind::quit()).unwrap();
72 let mut s_hup = signal(SignalKind::hangup()).unwrap();
73
74 async move {
76 tokio::select!(
77 _ = s_int.recv() => (),
78 _ = s_term.recv() => (),
79 _ = s_quit.recv() => (),
80 _ = s_hup.recv() => (),
81 );
82 Ok(())
83 }
84 }
85 #[cfg(not(target_family = "unix"))]
86 fn signal_listener() -> impl Future<Output = io::Result<()>> {
87 tokio::signal::ctrl_c()
88 }
89
90 let node_clone = node.clone();
91 tokio::task::spawn(async move {
92 match signal_listener().await {
93 Ok(()) => {
94 warn!("==========================================================================================");
95 warn!("⚠️ Attention - Starting the graceful shutdown procedure (ETA: 30 seconds)...");
96 warn!("⚠️ Attention - To avoid DATA CORRUPTION, do NOT interrupt snarkOS (or press Ctrl+C again)");
97 warn!("⚠️ Attention - Please wait until the shutdown gracefully completes (ETA: 30 seconds)");
98 warn!("==========================================================================================");
99
100 match node_clone.get() {
101 Some(node) => node.shut_down().await,
103 None => shutdown_flag.store(true, Ordering::Relaxed),
105 }
106
107 tokio::time::sleep(Duration::from_secs(3)).await;
109
110 std::process::exit(0);
112 }
113 Err(error) => error!("tokio::signal::ctrl_c encountered an error: {}", error),
114 }
115 });
116
117 node
118 }
119
120 async fn shut_down(&self);
122}