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