main.rs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::sync::{Arc, OnceLock};
  19. use darkfi::{
  20. async_daemonize, cli_desc,
  21. event_graph::{proto::ProtocolEventGraph, EventGraph, EventGraphPtr, NULL_ID},
  22. net::{session::SESSION_DEFAULT, settings::SettingsOpt, P2p},
  23. rpc::{
  24. jsonrpc::JsonSubscriber,
  25. server::{listen_and_serve, RequestHandler},
  26. settings::RpcSettingsOpt,
  27. },
  28. system::{sleep, StoppableTask},
  29. util::path::expand_path,
  30. Error, Result,
  31. };
  32. use sled_overlay::sled;
  33. use smol::{fs, lock::RwLock, stream::StreamExt};
  34. use structopt_toml::{serde::Deserialize, structopt::StructOpt, StructOptToml};
  35. use tracing::{debug, error, info};
  36. mod rpc;
  37. use rpc::JsonRpcInterface;
  38. const CONFIG_FILE: &str = "genev_config.toml";
  39. const CONFIG_FILE_CONTENTS: &str = include_str!("../genev_config.toml");
  40. #[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
  41. #[serde(default)]
  42. #[structopt(name = "genev", about = cli_desc!())]
  43. struct Args {
  44. #[structopt(short, long)]
  45. /// Configuration file to use
  46. config: Option<String>,
  47. #[structopt(flatten)]
  48. /// JSON-RPC settings
  49. rpc: RpcSettingsOpt,
  50. #[structopt(flatten)]
  51. /// P2P network settings
  52. net: SettingsOpt,
  53. #[structopt(long, default_value = "~/.local/share/darkfi/genev_db")]
  54. /// Sets Datastore Path
  55. datastore: String,
  56. #[structopt(short, long, default_value = "~/.local/share/darkfi/replayed_genev_db")]
  57. /// Replay logs (DB) path
  58. replay_datastore: String,
  59. #[structopt(long)]
  60. /// Flag to store Sled DB instructions
  61. replay_mode: bool,
  62. #[structopt(short, long)]
  63. /// Set log file to ouput into
  64. log: Option<String>,
  65. #[structopt(long)]
  66. /// Flag to skip syncing the DAG (no history)
  67. skip_dag_sync: bool,
  68. #[structopt(long)]
  69. // Whether to sync headers only or full sync
  70. pub fast_mode: bool,
  71. #[structopt(short, parse(from_occurrences))]
  72. /// Increase verbosity (-vvv supported)
  73. verbose: u8,
  74. }
  75. async fn start_sync_loop(
  76. event_graph: EventGraphPtr,
  77. last_sent: RwLock<blake3::Hash>,
  78. seen: OnceLock<sled::Tree>,
  79. ) -> Result<()> {
  80. let incoming = event_graph.event_pub.clone().subscribe().await;
  81. let seen_events = seen.get().unwrap();
  82. loop {
  83. let event = incoming.receive().await;
  84. let event_id = event.header.id();
  85. if *last_sent.read().await == event_id {
  86. continue
  87. }
  88. if seen_events.contains_key(event_id.as_bytes()).unwrap() {
  89. continue
  90. }
  91. debug!("new event: {event:?}");
  92. }
  93. }
  94. async_daemonize!(realmain);
  95. async fn realmain(settings: Args, executor: Arc<smol::Executor<'static>>) -> Result<()> {
  96. ////////////////////
  97. // Initialize the base structures
  98. ////////////////////
  99. info!("Instantiating event DAG");
  100. // Create datastore path if not there already.
  101. let datastore_path = expand_path(&settings.datastore)?;
  102. fs::create_dir_all(&datastore_path).await?;
  103. let replay_datastore = expand_path(&settings.replay_datastore)?;
  104. let replay_mode = settings.replay_mode;
  105. let fast_mode = settings.fast_mode;
  106. let sled_db = sled::open(datastore_path.clone())?;
  107. let p2p_settings: darkfi::net::Settings =
  108. (env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"), settings.net).try_into()?;
  109. let p2p = P2p::new(p2p_settings, executor.clone()).await?;
  110. let event_graph = EventGraph::new(
  111. p2p.clone(),
  112. sled_db.clone(),
  113. replay_datastore,
  114. replay_mode,
  115. fast_mode,
  116. 1,
  117. executor.clone(),
  118. )
  119. .await?;
  120. info!("Registering EventGraph P2P protocol");
  121. let event_graph_ = Arc::clone(&event_graph);
  122. let registry = p2p.protocol_registry();
  123. registry
  124. .register(SESSION_DEFAULT, move |channel, _| {
  125. let event_graph_ = event_graph_.clone();
  126. async move { ProtocolEventGraph::init(event_graph_, channel).await.unwrap() }
  127. })
  128. .await;
  129. // Run
  130. info!(target: "genevd", "Starting P2P network");
  131. p2p.clone().start().await?;
  132. info!(target: "genevd", "Waiting for some P2P connections...");
  133. sleep(5).await;
  134. match event_graph.static_sync().await {
  135. Ok(()) => {
  136. info!("static synced successfully")
  137. }
  138. Err(e) => {
  139. error!("failed syncing static graph: {e}");
  140. p2p.stop().await;
  141. return Err(Error::DagSyncFailed)
  142. }
  143. }
  144. // We'll attempt to sync 5 times
  145. if !settings.skip_dag_sync {
  146. for i in 1..=6 {
  147. info!("Syncing event DAG (attempt #{i})");
  148. match event_graph.sync_selected(1, settings.fast_mode).await {
  149. Ok(()) => break,
  150. Err(e) => {
  151. if i == 6 {
  152. error!("Failed syncing DAG. Exiting.");
  153. p2p.stop().await;
  154. return Err(Error::DagSyncFailed)
  155. } else {
  156. // TODO: Maybe at this point we should prune or something?
  157. // TODO: Or maybe just tell the user to delete the DAG from FS.
  158. error!("Failed syncing DAG ({e}), retrying in 10s...");
  159. sleep(10).await;
  160. }
  161. }
  162. }
  163. }
  164. } else {
  165. *event_graph.synced.write().await = true;
  166. }
  167. ////////////////////
  168. // Listner
  169. ////////////////////
  170. let last_sent = RwLock::new(NULL_ID);
  171. let seen = OnceLock::new();
  172. seen.set(sled_db.open_tree("genevdb").unwrap()).unwrap();
  173. info!(target: "genevd", "Starting sync loop task");
  174. let sync_loop_task = StoppableTask::new();
  175. sync_loop_task.clone().start(
  176. start_sync_loop(event_graph.clone(), last_sent, seen.clone()),
  177. |res| async {
  178. match res {
  179. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  180. Err(e) => error!(target: "genevd", "Failed starting sync loop task: {e}"),
  181. }
  182. },
  183. Error::DetachedTaskStopped,
  184. executor.clone(),
  185. );
  186. info!("Starting dnet subs task");
  187. let dnet_sub = JsonSubscriber::new("dnet.subscribe_events");
  188. let dnet_sub_ = dnet_sub.clone();
  189. let p2p_ = p2p.clone();
  190. let dnet_task = StoppableTask::new();
  191. dnet_task.clone().start(
  192. async move {
  193. let dnet_sub = p2p_.dnet_subscribe().await;
  194. loop {
  195. let event = dnet_sub.receive().await;
  196. debug!("Got dnet event: {event:?}");
  197. dnet_sub_.notify(vec![event.into()].into()).await;
  198. }
  199. },
  200. |res| async {
  201. match res {
  202. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  203. Err(e) => panic!("{e}"),
  204. }
  205. },
  206. Error::DetachedTaskStopped,
  207. executor.clone(),
  208. );
  209. info!("Starting deg subs task");
  210. let deg_sub = JsonSubscriber::new("deg.subscribe_events");
  211. let deg_sub_ = deg_sub.clone();
  212. let event_graph_ = event_graph.clone();
  213. let deg_task = StoppableTask::new();
  214. deg_task.clone().start(
  215. async move {
  216. let deg_sub = event_graph_.deg_subscribe().await;
  217. loop {
  218. let event = deg_sub.receive().await;
  219. debug!("Got deg event: {event:?}");
  220. deg_sub_.notify(vec![event.into()].into()).await;
  221. }
  222. },
  223. |res| async {
  224. match res {
  225. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  226. Err(e) => panic!("{e}"),
  227. }
  228. },
  229. Error::DetachedTaskStopped,
  230. executor.clone(),
  231. );
  232. //
  233. // RPC interface
  234. //
  235. let rpc_interface = Arc::new(JsonRpcInterface::new(
  236. "Alolymous".to_string(),
  237. event_graph.clone(),
  238. p2p.clone(),
  239. dnet_sub,
  240. deg_sub,
  241. ));
  242. let rpc_task = StoppableTask::new();
  243. let rpc_interface_ = rpc_interface.clone();
  244. rpc_task.clone().start(
  245. listen_and_serve(settings.rpc.into(), rpc_interface, None, executor.clone()),
  246. |res| async move {
  247. match res {
  248. Ok(()) | Err(Error::RpcServerStopped) => rpc_interface_.stop_connections().await,
  249. Err(e) => error!(target: "genevd", "Failed starting JSON-RPC server: {e}"),
  250. }
  251. },
  252. Error::RpcServerStopped,
  253. executor.clone(),
  254. );
  255. // Signal handling for graceful termination.
  256. let (signals_handler, signals_task) = SignalHandler::new(executor)?;
  257. signals_handler.wait_termination(signals_task).await?;
  258. info!("Caught termination signal, cleaning up and exiting...");
  259. info!(target: "genevd", "Stopping JSON-RPC server...");
  260. rpc_task.stop().await;
  261. info!(target: "genevd", "Stopping Debugging tasks...");
  262. dnet_task.stop().await;
  263. deg_task.stop().await;
  264. info!(target: "genevd", "Stopping sync loop task...");
  265. sync_loop_task.stop().await;
  266. // stop p2p
  267. p2p.stop().await;
  268. Ok(())
  269. }