mod.rs 32 KB

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