mod.rs 30 KB

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