mod.rs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  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::{
  19. collections::{BTreeMap, HashMap, HashSet, VecDeque},
  20. path::PathBuf,
  21. sync::Arc,
  22. };
  23. use darkfi_serial::{deserialize_async, serialize_async};
  24. use num_bigint::BigUint;
  25. use sled_overlay::{sled, SledTreeOverlay};
  26. use smol::{
  27. lock::{OnceCell, RwLock},
  28. Executor,
  29. };
  30. use tracing::{debug, error, info, warn};
  31. use crate::{
  32. event_graph::util::replayer_log,
  33. net::P2pPtr,
  34. system::{msleep, Publisher, PublisherPtr, StoppableTask, StoppableTaskPtr, Subscription},
  35. Error, Result,
  36. };
  37. #[cfg(feature = "rpc")]
  38. use {
  39. crate::rpc::{
  40. jsonrpc::{JsonResponse, JsonResult},
  41. util::json_map,
  42. },
  43. tinyjson::JsonValue::{self},
  44. };
  45. /// An event graph event
  46. pub mod event;
  47. pub use event::Event;
  48. /// P2P protocol implementation for the Event Graph
  49. pub mod proto;
  50. use proto::{EventRep, EventReq, TipRep, TipReq};
  51. /// Utility functions
  52. pub mod util;
  53. use util::{generate_genesis, millis_until_next_rotation, next_rotation_timestamp};
  54. // Debugging event graph
  55. pub mod deg;
  56. use deg::DegEvent;
  57. #[cfg(test)]
  58. mod tests;
  59. /// Initial genesis timestamp in millis (07 Sep 2023, 00:00:00 UTC)
  60. /// Must always be UTC midnight.
  61. pub const INITIAL_GENESIS: u64 = 1_694_044_800_000;
  62. /// Genesis event contents
  63. pub const GENESIS_CONTENTS: &[u8] = &[0x47, 0x45, 0x4e, 0x45, 0x53, 0x49, 0x53];
  64. /// The number of parents an event is supposed to have.
  65. pub const N_EVENT_PARENTS: usize = 5;
  66. /// Allowed timestamp drift in milliseconds
  67. const EVENT_TIME_DRIFT: u64 = 60_000;
  68. /// Null event ID
  69. pub const NULL_ID: blake3::Hash = blake3::Hash::from_bytes([0x00; blake3::OUT_LEN]);
  70. /// Atomic pointer to an [`EventGraph`] instance.
  71. pub type EventGraphPtr = Arc<EventGraph>;
  72. /// An Event Graph instance
  73. pub struct EventGraph {
  74. /// Pointer to the P2P network instance
  75. p2p: P2pPtr,
  76. /// Sled tree containing the DAG
  77. dag: sled::Tree,
  78. /// Replay logs path.
  79. datastore: PathBuf,
  80. /// Run in replay_mode where if set we log Sled DB instructions
  81. /// into `datastore`, useful to reacreate a faulty DAG to debug.
  82. replay_mode: bool,
  83. /// The set of unreferenced DAG tips
  84. unreferenced_tips: RwLock<BTreeMap<u64, HashSet<blake3::Hash>>>,
  85. /// A `HashSet` containg event IDs and their 1-level parents.
  86. /// These come from the events we've sent out using `EventPut`.
  87. /// They are used with `EventReq` to decide if we should reply
  88. /// or not. Additionally it is also used when we broadcast the
  89. /// `TipRep` message telling peers about our unreferenced tips.
  90. broadcasted_ids: RwLock<HashSet<blake3::Hash>>,
  91. /// DAG Pruning Task
  92. pub prune_task: OnceCell<StoppableTaskPtr>,
  93. /// Event publisher, this notifies whenever an event is
  94. /// inserted into the DAG
  95. pub event_pub: PublisherPtr<Event>,
  96. /// Current genesis event
  97. current_genesis: RwLock<Event>,
  98. /// Currently configured DAG rotation, in days
  99. days_rotation: u64,
  100. /// Flag signalling DAG has finished initial sync
  101. pub synced: RwLock<bool>,
  102. /// Enable graph debugging
  103. pub deg_enabled: RwLock<bool>,
  104. /// The publisher for which we can give deg info over
  105. deg_publisher: PublisherPtr<DegEvent>,
  106. }
  107. impl EventGraph {
  108. /// Create a new [`EventGraph`] instance, creates a new Genesis
  109. /// event and checks if it
  110. /// is containd in DAG, if not prunes DAG, may also start a pruning
  111. /// task based on `days_rotation`, and return an atomic instance of
  112. /// `Self`
  113. /// * `p2p` atomic pointer to p2p.
  114. /// * `sled_db` sled DB instance.
  115. /// * `datastore` path where we should log db instrucion if run in
  116. /// replay mode.
  117. /// * `replay_mode` set the flag to keep a log of db instructions.
  118. /// * `dag_tree_name` the name of disk-backed tree (or DAG name).
  119. /// * `days_rotation` marks the lifetime of the DAG before it's
  120. /// pruned.
  121. pub async fn new(
  122. p2p: P2pPtr,
  123. sled_db: sled::Db,
  124. datastore: PathBuf,
  125. replay_mode: bool,
  126. dag_tree_name: &str,
  127. days_rotation: u64,
  128. ex: Arc<Executor<'_>>,
  129. ) -> Result<EventGraphPtr> {
  130. let dag = sled_db.open_tree(dag_tree_name)?;
  131. let unreferenced_tips = RwLock::new(BTreeMap::new());
  132. let broadcasted_ids = RwLock::new(HashSet::new());
  133. let event_pub = Publisher::new();
  134. // Create the current genesis event based on the `days_rotation`
  135. let current_genesis = generate_genesis(days_rotation);
  136. let self_ = Arc::new(Self {
  137. p2p,
  138. dag: dag.clone(),
  139. datastore,
  140. replay_mode,
  141. unreferenced_tips,
  142. broadcasted_ids,
  143. prune_task: OnceCell::new(),
  144. event_pub,
  145. current_genesis: RwLock::new(current_genesis.clone()),
  146. days_rotation,
  147. synced: RwLock::new(false),
  148. deg_enabled: RwLock::new(false),
  149. deg_publisher: Publisher::new(),
  150. });
  151. // Check if we have it in our DAG.
  152. // If not, we can prune the DAG and insert this new genesis event.
  153. if !dag.contains_key(current_genesis.id().as_bytes())? {
  154. info!(
  155. target: "event_graph::new",
  156. "[EVENTGRAPH] DAG does not contain current genesis, pruning existing data",
  157. );
  158. self_.dag_prune(current_genesis).await?;
  159. }
  160. // Find the unreferenced tips in the current DAG state.
  161. *self_.unreferenced_tips.write().await = self_.find_unreferenced_tips().await;
  162. // Spawn the DAG pruning task
  163. if days_rotation > 0 {
  164. let prune_task = StoppableTask::new();
  165. let _ = self_.prune_task.set(prune_task.clone()).await;
  166. prune_task.clone().start(
  167. self_.clone().dag_prune_task(days_rotation),
  168. |res| async move {
  169. match res {
  170. Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
  171. Err(e) => error!(target: "event_graph::_handle_stop", "[EVENTGRAPH] Failed stopping prune task: {e}")
  172. }
  173. },
  174. Error::DetachedTaskStopped,
  175. ex.clone(),
  176. );
  177. }
  178. Ok(self_)
  179. }
  180. pub fn days_rotation(&self) -> u64 {
  181. self.days_rotation
  182. }
  183. /// Sync the DAG from connected peers
  184. pub async fn dag_sync(&self) -> Result<()> {
  185. // We do an optimistic sync where we ask all our connected peers for
  186. // the latest layer DAG tips (unreferenced events) and then we accept
  187. // the ones we see the most times.
  188. // * Compare received tips with local ones, identify which we are missing.
  189. // * Request these from peers
  190. // * Recursively request these backward
  191. //
  192. // Verification:
  193. // * Timestamps should go backwards
  194. // * Cross-check with multiple peers, this means we should request the
  195. // same event from multiple peers and make sure it is the same.
  196. // * Since we should be pruning, if we're not synced after some reasonable
  197. // amount of iterations, these could be faulty peers and we can try again
  198. // from the beginning
  199. // Get references to all our peers.
  200. let channels = self.p2p.hosts().peers();
  201. let mut communicated_peers = channels.len();
  202. info!(
  203. target: "event_graph::dag_sync",
  204. "[EVENTGRAPH] Syncing DAG from {communicated_peers} peers..."
  205. );
  206. // Here we keep track of the tips, their layers and how many time we've seen them.
  207. let mut tips: HashMap<blake3::Hash, (u64, usize)> = HashMap::new();
  208. // Let's first ask all of our peers for their tips and collect them
  209. // in our hashmap above.
  210. for channel in channels.iter() {
  211. let url = channel.display_address();
  212. let tip_rep_sub = match channel.subscribe_msg::<TipRep>().await {
  213. Ok(v) => v,
  214. Err(e) => {
  215. error!(
  216. target: "event_graph::dag_sync",
  217. "[EVENTGRAPH] Sync: Couldn't subscribe TipReq for peer {url}, skipping ({e})"
  218. );
  219. communicated_peers -= 1;
  220. continue
  221. }
  222. };
  223. if let Err(e) = channel.send(&TipReq {}).await {
  224. error!(
  225. target: "event_graph::dag_sync",
  226. "[EVENTGRAPH] Sync: Couldn't contact peer {url}, skipping ({e})"
  227. );
  228. communicated_peers -= 1;
  229. continue
  230. };
  231. let outbound_connect_timeout = self
  232. .p2p
  233. .settings()
  234. .read_arc()
  235. .await
  236. .outbound_connect_timeout(channel.address().scheme());
  237. // Node waits for response
  238. let Ok(peer_tips) = tip_rep_sub.receive_with_timeout(outbound_connect_timeout).await
  239. else {
  240. error!(
  241. target: "event_graph::dag_sync",
  242. "[EVENTGRAPH] Sync: Peer {url} didn't reply with tips in time, skipping"
  243. );
  244. communicated_peers -= 1;
  245. continue
  246. };
  247. let peer_tips = &peer_tips.0;
  248. // Note down the seen tips
  249. for (layer, layer_tips) in peer_tips {
  250. for tip in layer_tips {
  251. if let Some(seen_tip) = tips.get_mut(tip) {
  252. seen_tip.1 += 1;
  253. } else {
  254. tips.insert(*tip, (*layer, 1));
  255. }
  256. }
  257. }
  258. }
  259. // After we've communicated all the peers, let's see what happened.
  260. if tips.is_empty() {
  261. error!(
  262. target: "event_graph::dag_sync",
  263. "[EVENTGRAPH] Sync: Could not find any DAG tips",
  264. );
  265. return Err(Error::DagSyncFailed)
  266. }
  267. // We know the number of peers we've communicated with,
  268. // so we will consider events we saw at more than 2/3 of
  269. // those peers.
  270. let consideration_threshold = communicated_peers * 2 / 3;
  271. let mut considered_tips = HashSet::new();
  272. for (tip, (_, amount)) in tips.iter() {
  273. if amount > &consideration_threshold {
  274. considered_tips.insert(*tip);
  275. }
  276. }
  277. drop(tips);
  278. // Now begin fetching the events backwards.
  279. let mut missing_parents = HashSet::new();
  280. for tip in considered_tips.iter() {
  281. assert!(tip != &NULL_ID);
  282. if !self.dag.contains_key(tip.as_bytes()).unwrap() {
  283. missing_parents.insert(*tip);
  284. }
  285. }
  286. if missing_parents.is_empty() {
  287. *self.synced.write().await = true;
  288. info!(target: "event_graph::dag_sync", "[EVENTGRAPH] DAG synced successfully!");
  289. return Ok(())
  290. }
  291. info!(target: "event_graph::dag_sync", "[EVENTGRAPH] Fetching events");
  292. let mut received_events: BTreeMap<u64, Vec<Event>> = BTreeMap::new();
  293. let mut received_events_hashes = HashSet::new();
  294. while !missing_parents.is_empty() {
  295. let mut found_event = false;
  296. for channel in channels.iter() {
  297. let url = channel.display_address();
  298. debug!(
  299. target: "event_graph::dag_sync",
  300. "Requesting {missing_parents:?} from {url}..."
  301. );
  302. let ev_rep_sub = match channel.subscribe_msg::<EventRep>().await {
  303. Ok(v) => v,
  304. Err(e) => {
  305. error!(
  306. target: "event_graph::dag_sync",
  307. "[EVENTGRAPH] Sync: Couldn't subscribe EventRep for peer {url}, skipping ({e})"
  308. );
  309. continue
  310. }
  311. };
  312. let request_missing_events = missing_parents.clone().into_iter().collect();
  313. if let Err(e) = channel.send(&EventReq(request_missing_events)).await {
  314. error!(
  315. target: "event_graph::dag_sync",
  316. "[EVENTGRAPH] Sync: Failed communicating EventReq({missing_parents:?}) to {url}: {e}"
  317. );
  318. continue
  319. }
  320. let outbound_connect_timeout = self
  321. .p2p
  322. .settings()
  323. .read_arc()
  324. .await
  325. .outbound_connect_timeout(channel.address().scheme());
  326. // Node waits for response
  327. let Ok(parent) = ev_rep_sub.receive_with_timeout(outbound_connect_timeout).await
  328. else {
  329. error!(
  330. target: "event_graph::dag_sync",
  331. "[EVENTGRAPH] Sync: Timeout waiting for parents {missing_parents:?} from {url}"
  332. );
  333. continue
  334. };
  335. let parents = parent.0.clone();
  336. for parent in parents {
  337. let parent_id = parent.id();
  338. if !missing_parents.contains(&parent_id) {
  339. error!(
  340. target: "event_graph::dag_sync",
  341. "[EVENTGRAPH] Sync: Peer {url} replied with a wrong event: {}",
  342. parent.id()
  343. );
  344. continue
  345. }
  346. debug!(
  347. target: "event_graph::dag_sync",
  348. "Got correct parent event {parent_id}"
  349. );
  350. if let Some(layer_events) = received_events.get_mut(&parent.layer) {
  351. layer_events.push(parent.clone());
  352. } else {
  353. let layer_events = vec![parent.clone()];
  354. received_events.insert(parent.layer, layer_events);
  355. }
  356. received_events_hashes.insert(parent_id);
  357. missing_parents.remove(&parent_id);
  358. found_event = true;
  359. // See if we have the upper parents
  360. for upper_parent in parent.parents.iter() {
  361. if upper_parent == &NULL_ID {
  362. continue
  363. }
  364. if !missing_parents.contains(upper_parent) &&
  365. !received_events_hashes.contains(upper_parent) &&
  366. !self.dag.contains_key(upper_parent.as_bytes()).unwrap()
  367. {
  368. debug!(
  369. target: "event_graph::dag_sync",
  370. "Found upper missing parent event {upper_parent}"
  371. );
  372. missing_parents.insert(*upper_parent);
  373. }
  374. }
  375. }
  376. break
  377. }
  378. if !found_event {
  379. error!(
  380. target: "event_graph::dag_sync",
  381. "[EVENTGRAPH] Sync: Failed to get all events",
  382. );
  383. return Err(Error::DagSyncFailed)
  384. }
  385. } // <-- while !missing_parents.is_empty
  386. // At this point we should've got all the events.
  387. // We should add them to the DAG.
  388. let mut events = vec![];
  389. for (_, tips) in received_events {
  390. for tip in tips {
  391. events.push(tip);
  392. }
  393. }
  394. self.dag_insert(&events).await?;
  395. *self.synced.write().await = true;
  396. info!(target: "event_graph::dag_sync", "[EVENTGRAPH] DAG synced successfully!");
  397. Ok(())
  398. }
  399. /// Atomically prune the DAG and insert the given event as genesis.
  400. async fn dag_prune(&self, genesis_event: Event) -> Result<()> {
  401. debug!(target: "event_graph::dag_prune", "Pruning DAG...");
  402. // Acquire exclusive locks to unreferenced_tips, broadcasted_ids and
  403. // current_genesis while this operation is happening. We do this to
  404. // ensure that during the pruning operation, no other operations are
  405. // able to access the intermediate state which could lead to producing
  406. // the wrong state after pruning.
  407. let mut unreferenced_tips = self.unreferenced_tips.write().await;
  408. let mut broadcasted_ids = self.broadcasted_ids.write().await;
  409. let mut current_genesis = self.current_genesis.write().await;
  410. // Atomically clear the DAG and write the new genesis event.
  411. let mut batch = sled::Batch::default();
  412. for key in self.dag.iter().keys() {
  413. batch.remove(key.unwrap());
  414. }
  415. batch.insert(genesis_event.id().as_bytes(), serialize_async(&genesis_event).await);
  416. debug!(target: "event_graph::dag_prune", "Applying batch...");
  417. if let Err(e) = self.dag.apply_batch(batch) {
  418. panic!("Failed pruning DAG, sled apply_batch error: {e}");
  419. }
  420. // Clear unreferenced tips and bcast ids
  421. *unreferenced_tips = BTreeMap::new();
  422. unreferenced_tips.insert(0, HashSet::from([genesis_event.id()]));
  423. *current_genesis = genesis_event;
  424. *broadcasted_ids = HashSet::new();
  425. drop(unreferenced_tips);
  426. drop(broadcasted_ids);
  427. drop(current_genesis);
  428. debug!(target: "event_graph::dag_prune", "DAG pruned successfully");
  429. Ok(())
  430. }
  431. /// Background task periodically pruning the DAG.
  432. async fn dag_prune_task(self: Arc<Self>, days_rotation: u64) -> Result<()> {
  433. // The DAG should periodically be pruned. This can be a configurable
  434. // parameter. By pruning, we should deterministically replace the
  435. // genesis event (can use a deterministic timestamp) and drop everything
  436. // in the DAG, leaving just the new genesis event.
  437. debug!(target: "event_graph::dag_prune_task", "Spawned background DAG pruning task");
  438. loop {
  439. // Find the next rotation timestamp:
  440. let next_rotation = next_rotation_timestamp(INITIAL_GENESIS, days_rotation);
  441. // Prepare the new genesis event
  442. let current_genesis = Event {
  443. timestamp: next_rotation,
  444. content: GENESIS_CONTENTS.to_vec(),
  445. parents: [NULL_ID; N_EVENT_PARENTS],
  446. layer: 0,
  447. };
  448. // Sleep until it's time to rotate.
  449. let s = millis_until_next_rotation(next_rotation);
  450. debug!(target: "event_graph::dag_prune_task", "Sleeping {s}ms until next DAG prune");
  451. msleep(s).await;
  452. debug!(target: "event_graph::dag_prune_task", "Rotation period reached");
  453. // Trigger DAG prune
  454. self.dag_prune(current_genesis).await?;
  455. }
  456. }
  457. /// Atomically insert given events into the DAG and return the event IDs.
  458. /// All provided events must be valid. An overlay is used over the DAG tree,
  459. /// temporary writting each event in order. After all events have been
  460. /// validated and inserted successfully, we write the overlay to sled.
  461. /// This will append the new events into the unreferenced tips set, and
  462. /// remove the events' parents from it. It will also append the events'
  463. /// level-1 parents to the `broadcasted_ids` set, so the P2P protocol
  464. /// knows that any requests for them are actually legitimate.
  465. /// TODO: The `broadcasted_ids` set should periodically be pruned, when
  466. /// some sensible time has passed after broadcasting the event.
  467. pub async fn dag_insert(&self, events: &[Event]) -> Result<Vec<blake3::Hash>> {
  468. // Sanity check
  469. if events.is_empty() {
  470. return Ok(vec![])
  471. }
  472. // Acquire exclusive locks to `unreferenced_tips and broadcasted_ids`
  473. let mut unreferenced_tips = self.unreferenced_tips.write().await;
  474. let mut broadcasted_ids = self.broadcasted_ids.write().await;
  475. // Here we keep the IDs to return
  476. let mut ids = Vec::with_capacity(events.len());
  477. // Create an overlay over the DAG tree
  478. let mut overlay = SledTreeOverlay::new(&self.dag);
  479. // Grab genesis timestamp
  480. let genesis_timestamp = self.current_genesis.read().await.timestamp;
  481. // Iterate over given events to validate them and
  482. // write them to the overlay
  483. for event in events {
  484. let event_id = event.id();
  485. debug!(
  486. target: "event_graph::dag_insert",
  487. "Inserting event {event_id} into the DAG"
  488. );
  489. if !event
  490. .validate(&self.dag, genesis_timestamp, self.days_rotation, Some(&overlay))
  491. .await?
  492. {
  493. error!(target: "event_graph::dag_insert", "Event {event_id} is invalid!");
  494. return Err(Error::EventIsInvalid)
  495. }
  496. let event_se = serialize_async(event).await;
  497. // Add the event to the overlay
  498. overlay.insert(event_id.as_bytes(), &event_se)?;
  499. if self.replay_mode {
  500. replayer_log(&self.datastore, "insert".to_owned(), event_se)?;
  501. }
  502. // Note down the event ID to return
  503. ids.push(event_id);
  504. }
  505. // Aggregate changes into a single batch
  506. let batch = overlay.aggregate().unwrap();
  507. // Atomically apply the batch.
  508. // Panic if something is corrupted.
  509. if let Err(e) = self.dag.apply_batch(batch) {
  510. panic!("Failed applying dag_insert batch to sled: {e}");
  511. }
  512. // Iterate over given events to update references and
  513. // send out notifications about them
  514. for event in events {
  515. let event_id = event.id();
  516. // Update the unreferenced DAG tips set
  517. debug!(
  518. target: "event_graph::dag_insert",
  519. "Event {event_id} parents {:#?}", event.parents,
  520. );
  521. for parent_id in event.parents.iter() {
  522. if parent_id != &NULL_ID {
  523. debug!(
  524. target: "event_graph::dag_insert",
  525. "Removing {parent_id} from unreferenced_tips"
  526. );
  527. // Iterate over unreferenced tips in previous layers
  528. // and remove the parent
  529. // NOTE: this might be too exhaustive, but the
  530. // assumption is that previous layers unreferenced
  531. // tips will be few.
  532. for (layer, tips) in unreferenced_tips.iter_mut() {
  533. if layer >= &event.layer {
  534. continue
  535. }
  536. tips.remove(parent_id);
  537. }
  538. broadcasted_ids.insert(*parent_id);
  539. }
  540. }
  541. unreferenced_tips.retain(|_, tips| !tips.is_empty());
  542. debug!(
  543. target: "event_graph::dag_insert",
  544. "Adding {event_id} to unreferenced tips"
  545. );
  546. if let Some(layer_tips) = unreferenced_tips.get_mut(&event.layer) {
  547. layer_tips.insert(event_id);
  548. } else {
  549. let mut layer_tips = HashSet::new();
  550. layer_tips.insert(event_id);
  551. unreferenced_tips.insert(event.layer, layer_tips);
  552. }
  553. // Send out notifications about the new event
  554. self.event_pub.notify(event.clone()).await;
  555. }
  556. // Drop the exclusive locks
  557. drop(unreferenced_tips);
  558. drop(broadcasted_ids);
  559. Ok(ids)
  560. }
  561. /// Fetch an event from the DAG
  562. pub async fn dag_get(&self, event_id: &blake3::Hash) -> Result<Option<Event>> {
  563. let Some(bytes) = self.dag.get(event_id.as_bytes())? else { return Ok(None) };
  564. let event: Event = deserialize_async(&bytes).await?;
  565. Ok(Some(event))
  566. }
  567. /// Get next layer along with its N_EVENT_PARENTS from the unreferenced
  568. /// tips of the DAG. Since tips are mapped by their layer, we go backwards
  569. /// until we fill the vector, ensuring we always use latest layers tips as
  570. /// parents.
  571. async fn get_next_layer_with_parents(&self) -> (u64, [blake3::Hash; N_EVENT_PARENTS]) {
  572. let unreferenced_tips = self.unreferenced_tips.read().await;
  573. let mut parents = [NULL_ID; N_EVENT_PARENTS];
  574. let mut index = 0;
  575. 'outer: for (_, tips) in unreferenced_tips.iter().rev() {
  576. for tip in tips.iter() {
  577. parents[index] = *tip;
  578. index += 1;
  579. if index >= N_EVENT_PARENTS {
  580. break 'outer
  581. }
  582. }
  583. }
  584. let next_layer = unreferenced_tips.last_key_value().unwrap().0 + 1;
  585. assert!(parents.iter().any(|x| x != &NULL_ID));
  586. (next_layer, parents)
  587. }
  588. /// Find the unreferenced tips in the current DAG state, mapped by their layers.
  589. async fn find_unreferenced_tips(&self) -> BTreeMap<u64, HashSet<blake3::Hash>> {
  590. // First get all the event IDs
  591. let mut tips = HashSet::new();
  592. for iter_elem in self.dag.iter() {
  593. let (id, _) = iter_elem.unwrap();
  594. let id = blake3::Hash::from_bytes((&id as &[u8]).try_into().unwrap());
  595. tips.insert(id);
  596. }
  597. // Iterate again to find unreferenced IDs
  598. for iter_elem in self.dag.iter() {
  599. let (_, event) = iter_elem.unwrap();
  600. let event: Event = deserialize_async(&event).await.unwrap();
  601. for parent in event.parents.iter() {
  602. tips.remove(parent);
  603. }
  604. }
  605. // Build the layers map
  606. let mut map: BTreeMap<u64, HashSet<blake3::Hash>> = BTreeMap::new();
  607. for tip in tips {
  608. let event = self.dag_get(&tip).await.unwrap().unwrap();
  609. if let Some(layer_tips) = map.get_mut(&event.layer) {
  610. layer_tips.insert(tip);
  611. } else {
  612. let mut layer_tips = HashSet::new();
  613. layer_tips.insert(tip);
  614. map.insert(event.layer, layer_tips);
  615. }
  616. }
  617. map
  618. }
  619. /// Internal function used for DAG sorting.
  620. async fn get_unreferenced_tips_sorted(&self) -> [blake3::Hash; N_EVENT_PARENTS] {
  621. let (_, tips) = self.get_next_layer_with_parents().await;
  622. // Convert the hash to BigUint for sorting
  623. let mut sorted: Vec<_> =
  624. tips.iter().map(|x| BigUint::from_bytes_be(x.as_bytes())).collect();
  625. sorted.sort_unstable();
  626. // Convert back to blake3
  627. let mut tips_sorted = [NULL_ID; N_EVENT_PARENTS];
  628. for (i, id) in sorted.iter().enumerate() {
  629. let mut bytes = id.to_bytes_be();
  630. // Ensure we have 32 bytes
  631. while bytes.len() < blake3::OUT_LEN {
  632. bytes.insert(0, 0);
  633. }
  634. tips_sorted[i] = blake3::Hash::from_bytes(bytes.try_into().unwrap());
  635. }
  636. tips_sorted
  637. }
  638. /// Perform a topological sort of the DAG.
  639. pub async fn order_events(&self) -> Vec<Event> {
  640. let mut ordered_events = VecDeque::new();
  641. let mut visited = HashSet::new();
  642. for tip in self.get_unreferenced_tips_sorted().await {
  643. if !visited.contains(&tip) && tip != NULL_ID {
  644. let tip = self.dag_get(&tip).await.unwrap().unwrap();
  645. ordered_events.extend(self.dfs_topological_sort(tip, &mut visited).await);
  646. }
  647. }
  648. let mut ord_events_vec = ordered_events.make_contiguous().to_vec();
  649. // Order events based on thier layer numbers, or based on timestamp if they are equal
  650. ord_events_vec
  651. .sort_unstable_by(|a, b| a.0.cmp(&b.0).then(b.1.timestamp.cmp(&a.1.timestamp)));
  652. ord_events_vec.iter().map(|a| a.1.clone()).collect::<Vec<Event>>()
  653. }
  654. /// We do a non-recursive DFS (<https://en.wikipedia.org/wiki/Depth-first_search>),
  655. /// and additionally we consider the timestamps.
  656. async fn dfs_topological_sort(
  657. &self,
  658. event: Event,
  659. visited: &mut HashSet<blake3::Hash>,
  660. ) -> VecDeque<(u64, Event)> {
  661. let mut ordered_events = VecDeque::new();
  662. let mut stack = VecDeque::new();
  663. let event_id = event.id();
  664. stack.push_back(event_id);
  665. while let Some(event_id) = stack.pop_front() {
  666. if !visited.contains(&event_id) && event_id != NULL_ID {
  667. visited.insert(event_id);
  668. if let Some(event) = self.dag_get(&event_id).await.unwrap() {
  669. for parent in event.parents.iter() {
  670. stack.push_back(*parent);
  671. }
  672. ordered_events.push_back((event.layer, event))
  673. }
  674. }
  675. }
  676. ordered_events
  677. }
  678. /// Enable graph debugging
  679. pub async fn deg_enable(&self) {
  680. *self.deg_enabled.write().await = true;
  681. warn!("[EVENTGRAPH] Graph debugging enabled!");
  682. }
  683. /// Disable graph debugging
  684. pub async fn deg_disable(&self) {
  685. *self.deg_enabled.write().await = false;
  686. warn!("[EVENTGRAPH] Graph debugging disabled!");
  687. }
  688. /// Subscribe to deg events
  689. pub async fn deg_subscribe(&self) -> Subscription<DegEvent> {
  690. self.deg_publisher.clone().subscribe().await
  691. }
  692. /// Send a deg notification over the publisher
  693. pub async fn deg_notify(&self, event: DegEvent) {
  694. self.deg_publisher.notify(event).await;
  695. }
  696. #[cfg(feature = "rpc")]
  697. pub async fn eventgraph_info(&self, id: u16, _params: JsonValue) -> JsonResult {
  698. let mut graph = HashMap::new();
  699. for iter_elem in self.dag.iter() {
  700. let (id, val) = iter_elem.unwrap();
  701. let id = blake3::Hash::from_bytes((&id as &[u8]).try_into().unwrap());
  702. let val: Event = deserialize_async(&val).await.unwrap();
  703. graph.insert(id, val);
  704. }
  705. let json_graph = graph
  706. .into_iter()
  707. .map(|(k, v)| {
  708. let key = k.to_string();
  709. let value = JsonValue::from(v);
  710. (key, value)
  711. })
  712. .collect();
  713. let values = json_map([("dag", JsonValue::Object(json_graph))]);
  714. let result = JsonValue::Object(HashMap::from([("eventgraph_info".to_string(), values)]));
  715. JsonResponse::new(result, id).into()
  716. }
  717. /// Fetch all the events that are on a higher layers than the
  718. /// provided ones.
  719. pub async fn fetch_successors_of(
  720. &self,
  721. tips: BTreeMap<u64, HashSet<blake3::Hash>>,
  722. ) -> Result<Vec<Event>> {
  723. debug!(
  724. target: "event_graph::fetch_successors_of",
  725. "fetching successors of {tips:?}"
  726. );
  727. let mut graph = HashMap::new();
  728. for iter_elem in self.dag.iter() {
  729. let (id, val) = iter_elem.unwrap();
  730. let hash = blake3::Hash::from_bytes((&id as &[u8]).try_into().unwrap());
  731. let event: Event = deserialize_async(&val).await.unwrap();
  732. graph.insert(hash, event);
  733. }
  734. let mut result = vec![];
  735. 'outer: for tip in tips.iter() {
  736. for i in tip.1.iter() {
  737. if !graph.contains_key(i) {
  738. continue 'outer;
  739. }
  740. }
  741. for (_, ev) in graph.iter() {
  742. if ev.layer > *tip.0 && !result.contains(ev) {
  743. result.push(ev.clone())
  744. }
  745. }
  746. }
  747. result.sort_by(|a, b| a.layer.cmp(&b.layer));
  748. Ok(result)
  749. }
  750. }