Prechádzať zdrojové kódy

event_graph: increase number of dags to 24, and decrease rotation periods to 1hr

dasman 10 mesiacov pred
rodič
commit
e75c9936b1

+ 4 - 4
bin/darkirc/darkirc_config.toml

@@ -10,10 +10,10 @@
 ## TLS secret key path if IRC acceptor uses TLS (optional)
 #irc_tls_secret = "/etc/letsencrypt/darkirc/privkey.pem"
 
-## How many DAGs to be synced (currently each DAG represents a 24hr msg
-## history counting from UTC midnight), increasing this number means 
-## you get/sync previous days msg history as well (max. 5) 
-#dags_count = 1
+## How many DAGs to be synced (each DAG represents a 1hr msg history),
+## increasing this number means you get/sync previous hours msg history 
+## as well (max. 24)
+#dags_count = 8
 
 ## Sets Datastore Path
 #datastore = "~/.local/share/darkfi/darkirc/darkirc_db"

+ 1 - 1
bin/darkirc/src/main.rs

@@ -95,7 +95,7 @@ struct Args {
     irc_tls_secret: Option<String>,
 
     /// How many DAGs to sync.
-    #[structopt(short, long, default_value = "1")]
+    #[structopt(short, long, default_value = "8")]
     dags_count: usize,
 
     #[structopt(short, long, default_value = "~/.local/share/darkfi/darkirc_db")]

+ 3 - 3
contrib/localnet/darkirc-four-nodes/darkirc_full_node1.toml

@@ -1,9 +1,9 @@
 ## IRC listen URL
 irc_listen = "tcp://127.0.0.1:22022"
 
-## How many DAGs to be synced (currently each DAG represents a 24hr msg
-## history counting from UTC midnight), increasing this number means 
-## you get/sync previous days msg history as well (max. 5) 
+## How many DAGs to be synced (each DAG represents a 1hr msg history),
+## increasing this number means you get/sync previous hours msg history 
+## as well (max. 24)
 dags_count = 1
 
 ## Sets Datastore Path

+ 3 - 3
contrib/localnet/darkirc-four-nodes/darkirc_full_node2.toml

@@ -1,9 +1,9 @@
 ## IRC listen URL
 irc_listen = "tcp://127.0.0.1:22023"
 
-## How many DAGs to be synced (currently each DAG represents a 24hr msg
-## history counting from UTC midnight), increasing this number means 
-## you get/sync previous days msg history as well (max. 5) 
+## How many DAGs to be synced (each DAG represents a 1hr msg history),
+## increasing this number means you get/sync previous hours msg history 
+## as well (max. 24)
 dags_count = 1
 
 ## Sets Datastore Path

+ 3 - 3
contrib/localnet/darkirc-four-nodes/darkirc_full_node3.toml

@@ -1,9 +1,9 @@
 ## IRC listen URL
 irc_listen = "tcp://127.0.0.1:22024"
 
-## How many DAGs to be synced (currently each DAG represents a 24hr msg
-## history counting from UTC midnight), increasing this number means 
-## you get/sync previous days msg history as well (max. 5) 
+## How many DAGs to be synced (each DAG represents a 1hr msg history),
+## increasing this number means you get/sync previous hours msg history 
+## as well (max. 24)
 dags_count = 1
 
 ## Sets Datastore Path

+ 4 - 4
contrib/localnet/darkirc-four-nodes/darkirc_full_node4.toml

@@ -1,10 +1,10 @@
 ## IRC listen URL
 irc_listen = "tcp://127.0.0.1:22025"
 
-## How many DAGs to be synced (currently each DAG represents a 24hr msg
-## history counting from UTC midnight), increasing this number means 
-## you get/sync previous days msg history as well (max. 5) 
-dags_count = 3
+## How many DAGs to be synced (each DAG represents a 1hr msg history),
+## increasing this number means you get/sync previous hours msg history 
+## as well (max. 24)
+dags_count = 8
 
 ## Sets Datastore Path
 datastore = "darkirc4"

+ 13 - 15
src/event_graph/event.rs

@@ -22,7 +22,7 @@ use darkfi_serial::{async_trait, deserialize_async, Encodable, SerialDecodable,
 use sled_overlay::{sled, SledTreeOverlay};
 use tracing::info;
 
-use crate::Result;
+use crate::{event_graph::util::generate_genesis, Result};
 
 use super::{
     util::next_rotation_timestamp, EventGraph, EVENT_TIME_DRIFT, INITIAL_GENESIS, NULL_ID,
@@ -71,13 +71,21 @@ impl Header {
     pub async fn validate(
         &self,
         header_dag: &sled::Tree,
-        days_rotation: u64,
+        hours_rotation: u64,
         overlay: Option<&SledTreeOverlay>,
     ) -> Result<bool> {
+        // Check if the event is not older than the oldest genesis
+        let genesis_timestamp = generate_genesis(1).header.timestamp;
+        // A day ago genesis same hour
+        let oldest_genesis_ts = genesis_timestamp - 86_400_000u64;
+        if self.timestamp < oldest_genesis_ts - EVENT_TIME_DRIFT {
+            return Ok(false)
+        }
+
         // If a rotation has been set, check if the event timestamp
         // is after the next genesis timestamp
-        if days_rotation > 0 {
-            let next_genesis_timestamp = next_rotation_timestamp(INITIAL_GENESIS, days_rotation);
+        if hours_rotation > 0 {
+            let next_genesis_timestamp = next_rotation_timestamp(INITIAL_GENESIS, hours_rotation);
             if self.timestamp > next_genesis_timestamp + EVENT_TIME_DRIFT {
                 return Ok(false)
             }
@@ -158,16 +166,6 @@ impl Event {
         &self.content
     }
 
-    /// Fully validate an event for the correct layout against provided
-    /// DAG [`sled::Tree`] reference and enforce relevant age, assuming
-    /// some possibility for a time drift. Optionally, provide an overlay
-    /// to use that instead of actual referenced DAG.
-    /// TODO: is this necessary? we validate headers and events should
-    /// be downloaded into the correct structure.
-    // pub async fn validate(&self) -> Result<bool> {
-    //     Ok(true)
-    // }
-
     /// Fully validate an event for the correct layout against provided
     /// [`EventGraph`] reference and enforce relevant age, assuming some
     /// possibility for a time drift.
@@ -281,7 +279,7 @@ mod tests {
             assert!(!event_empty_content.dag_validate(&header_dag).await?);
 
             let mut event_timestamp_too_old = valid_event.clone();
-            event_timestamp_too_old.header.timestamp = 0;
+            event_timestamp_too_old.header.timestamp = 1000;
             assert!(!event_timestamp_too_old.dag_validate(&header_dag).await?);
 
             let mut event_timestamp_too_new = valid_event.clone();

+ 27 - 24
src/event_graph/mod.rs

@@ -43,7 +43,7 @@ use tracing::{debug, error, info, warn};
 use url::Url;
 
 use crate::{
-    event_graph::util::{midnight_timestamp, replayer_log},
+    event_graph::util::{next_hour_timestamp, next_rotation_timestamp, replayer_log},
     net::{channel::Channel, P2pPtr},
     system::{msleep, Publisher, PublisherPtr, StoppableTask, StoppableTaskPtr, Subscription},
     Error, Result,
@@ -68,7 +68,7 @@ use proto::{EventRep, EventReq, HeaderRep, HeaderReq, TipRep, TipReq};
 
 /// Utility functions
 pub mod util;
-use util::{generate_genesis, millis_until_next_rotation, next_rotation_timestamp};
+use util::{generate_genesis, millis_until_next_rotation};
 
 // Debugging event graph
 pub mod deg;
@@ -91,7 +91,7 @@ const EVENT_TIME_DRIFT: u64 = 60_000;
 pub const NULL_ID: Hash = Hash::from_bytes([0x00; blake3::OUT_LEN]);
 
 /// Maximum number of DAGs to store, this should be configurable
-pub const DAGS_MAX_NUMBER: i8 = 5;
+pub const DAGS_MAX_NUMBER: i8 = 24;
 
 /// Atomic pointer to an [`EventGraph`] instance.
 pub type EventGraphPtr = Arc<EventGraph>;
@@ -105,15 +105,18 @@ pub struct DAGStore {
 }
 
 impl DAGStore {
-    pub async fn new(&self, sled_db: sled::Db, days_rotation: u64) -> Self {
+    pub async fn new(&self, sled_db: sled::Db, hours_rotation: u64) -> Self {
         let mut considered_trees = HashMap::new();
         let mut considered_header_trees = HashMap::new();
-        if days_rotation > 0 {
+        if hours_rotation > 0 {
             // Create previous genesises if not existing, since they are deterministic.
             for i in 1..=DAGS_MAX_NUMBER {
-                let i_days_ago = midnight_timestamp((i - DAGS_MAX_NUMBER).into());
-                let header =
-                    Header { timestamp: i_days_ago, parents: [NULL_ID; N_EVENT_PARENTS], layer: 0 };
+                let i_hours_ago = next_hour_timestamp((i - DAGS_MAX_NUMBER).into());
+                let header = Header {
+                    timestamp: i_hours_ago,
+                    parents: [NULL_ID; N_EVENT_PARENTS],
+                    layer: 0,
+                };
                 let genesis = Event { header, content: GENESIS_CONTENTS.to_vec() };
 
                 let tree_name = genesis.id().to_string();
@@ -359,8 +362,8 @@ pub struct EventGraph {
     pub event_pub: PublisherPtr<Event>,
     /// Current genesis event
     pub current_genesis: RwLock<Event>,
-    /// Currently configured DAG rotation, in days
-    days_rotation: u64,
+    /// Currently configured DAG rotation, in hours
+    hours_rotation: u64,
     /// Flag signalling DAG has finished initial sync
     pub synced: RwLock<bool>,
     /// Enable graph debugging
@@ -376,14 +379,14 @@ impl EventGraph {
     /// Create a new [`EventGraph`] instance, creates a new Genesis
     /// event and checks if it
     /// is containd in DAG, if not prunes DAG, may also start a pruning
-    /// task based on `days_rotation`, and return an atomic instance of
+    /// task based on `hours_rotation`, and return an atomic instance of
     /// `Self`
     /// * `p2p` atomic pointer to p2p.
     /// * `sled_db` sled DB instance.
     /// * `datastore` path where we should log db instrucion if run in
     ///   replay mode.
     /// * `replay_mode` set the flag to keep a log of db instructions.
-    /// * `days_rotation` marks the lifetime of the DAG before it's
+    /// * `hours_rotation` marks the lifetime of the DAG before it's
     ///   pruned.
     pub async fn new(
         p2p: P2pPtr,
@@ -391,21 +394,21 @@ impl EventGraph {
         datastore: PathBuf,
         replay_mode: bool,
         fast_mode: bool,
-        days_rotation: u64,
+        hours_rotation: u64,
         ex: Arc<Executor<'_>>,
     ) -> Result<EventGraphPtr> {
         let broadcasted_ids = RwLock::new(HashSet::new());
         let event_pub = Publisher::new();
 
-        // Create the current genesis event based on the `days_rotation`
-        let current_genesis = generate_genesis(days_rotation);
+        // Create the current genesis event based on the `hours_rotation`
+        let current_genesis = generate_genesis(hours_rotation);
         let current_dag_tree_name = current_genesis.id().to_string();
         let dag_store = DAGStore {
             db: sled_db.clone(),
             header_dags: HashMap::default(),
             main_dags: HashMap::default(),
         }
-        .new(sled_db, days_rotation)
+        .new(sled_db, hours_rotation)
         .await;
 
         let self_ = Arc::new(Self {
@@ -418,7 +421,7 @@ impl EventGraph {
             prune_task: OnceCell::new(),
             event_pub,
             current_genesis: RwLock::new(current_genesis.clone()),
-            days_rotation,
+            hours_rotation,
             synced: RwLock::new(false),
             deg_enabled: RwLock::new(false),
             deg_publisher: Publisher::new(),
@@ -436,12 +439,12 @@ impl EventGraph {
         }
 
         // Spawn the DAG pruning task
-        if days_rotation > 0 {
+        if hours_rotation > 0 {
             let prune_task = StoppableTask::new();
             let _ = self_.prune_task.set(prune_task.clone()).await;
 
             prune_task.clone().start(
-                 self_.clone().dag_prune_task(days_rotation),
+                 self_.clone().dag_prune_task(hours_rotation),
                  |res| async move {
                      match res {
                          Ok(()) | Err(Error::DetachedTaskStopped) => { /* Do nothing */ }
@@ -456,8 +459,8 @@ impl EventGraph {
         Ok(self_)
     }
 
-    pub fn days_rotation(&self) -> u64 {
-        self.days_rotation
+    pub fn hours_rotation(&self) -> u64 {
+        self.hours_rotation
     }
 
     /// Sync the DAG from connected peers
@@ -742,7 +745,7 @@ impl EventGraph {
     }
 
     /// Background task periodically pruning the DAG.
-    async fn dag_prune_task(self: Arc<Self>, days_rotation: u64) -> Result<()> {
+    async fn dag_prune_task(self: Arc<Self>, hours_rotation: u64) -> Result<()> {
         // The DAG should periodically be pruned. This can be a configurable
         // parameter. By pruning, we should deterministically replace the
         // genesis event (can use a deterministic timestamp) and drop everything
@@ -751,7 +754,7 @@ impl EventGraph {
 
         loop {
             // Find the next rotation timestamp:
-            let next_rotation = next_rotation_timestamp(INITIAL_GENESIS, days_rotation);
+            let next_rotation = next_rotation_timestamp(INITIAL_GENESIS, hours_rotation);
 
             let header =
                 Header { timestamp: next_rotation, parents: [NULL_ID; N_EVENT_PARENTS], layer: 0 };
@@ -946,7 +949,7 @@ impl EventGraph {
                 target: "event_graph::header_dag_insert()",
                 "Inserting header {} into the DAG", header_id,
             );
-            if !header.validate(&header_dag, self.days_rotation, Some(&overlay)).await? {
+            if !header.validate(&header_dag, self.hours_rotation, Some(&overlay)).await? {
                 error!(target: "event_graph::header_dag_insert()", "Header {} is invalid!", header_id);
                 return Err(Error::HeaderIsInvalid)
             }

+ 51 - 51
src/event_graph/util.rs

@@ -47,33 +47,33 @@ use {
 
 use super::event::Header;
 
-/// MilliSeconds in a day
-pub(super) const DAY: i64 = 86_400_000;
+/// MilliSeconds in an hour
+pub(super) const HOUR: i64 = 3_600_000;
 
-/// Calculate the midnight timestamp given a number of days.
-/// If `days` is 0, calculate the midnight timestamp of today.
-pub(super) fn midnight_timestamp(days: i64) -> u64 {
+/// Calculate the next hour timestamp given a number of hours.
+/// If `hours` is 0, calculate the timestamp of this hour.
+pub(super) fn next_hour_timestamp(hours: i64) -> u64 {
     // Get current time
     let now = UNIX_EPOCH.elapsed().unwrap().as_millis() as i64;
 
-    // Find the timestamp for the midnight of the current day
-    let cur_midnight = (now / DAY) * DAY;
+    // Find the timestamp for the next hour
+    let next_hour = (now / HOUR) * HOUR;
 
-    // Adjust for days_from_now
-    (cur_midnight + (DAY * days)) as u64
+    // Adjust for hours_from_now
+    (next_hour + (HOUR * hours)) as u64
 }
 
-/// Calculate the number of days since a given midnight timestamp.
-pub(super) fn days_since(midnight_ts: u64) -> u64 {
+/// Calculate the number of hours since a given timestamp.
+pub(super) fn hours_since(next_hour_ts: u64) -> u64 {
     // Get current time
     let now = UNIX_EPOCH.elapsed().unwrap().as_millis() as u64;
 
     // Calculate the difference between the current timestamp
     // and the given midnight timestamp
-    let elapsed_seconds = now - midnight_ts;
+    let elapsed_seconds = now - next_hour_ts;
 
-    // Convert the elapsed seconds into days
-    elapsed_seconds / DAY as u64
+    // Convert the elapsed seconds into hours
+    elapsed_seconds / HOUR as u64
 }
 
 /// Calculate the timestamp of the next DAG rotation.
@@ -82,26 +82,26 @@ pub fn next_rotation_timestamp(starting_timestamp: u64, rotation_period: u64) ->
     if rotation_period == 0 {
         panic!("Rotation period cannot be 0");
     }
-    // Calculate the number of days since the given starting point
-    let days_passed = days_since(starting_timestamp);
+    // Calculate the number of hours since the given starting point
+    let hours_passed = hours_since(starting_timestamp);
 
     // Find out how many rotation periods have occurred since
     // the starting point.
-    // Note: when rotation_period = 1, rotations_since_start = days_passed
-    let rotations_since_start = days_passed.div_ceil(rotation_period);
+    // Note: when rotation_period = 1, rotations_since_start = hours_passed
+    let rotations_since_start = hours_passed.div_ceil(rotation_period);
 
-    // Find out the number of days until the next rotation. Panic if result is beyond the range
+    // Find out the number of hours until the next rotation. Panic if result is beyond the range
     // of i64.
-    let days_until_next_rotation: i64 =
-        (rotations_since_start * rotation_period - days_passed).try_into().unwrap();
+    let hours_until_next_rotation: i64 =
+        (rotations_since_start * rotation_period - hours_passed).try_into().unwrap();
 
     // Get the timestamp for the next rotation
-    if days_until_next_rotation == 0 {
-        // If there are 0 days until the next rotation, we want
-        // to rotate tomorrow, at midnight. This is a special case.
-        return midnight_timestamp(1)
+    if hours_until_next_rotation == 0 {
+        // If there are 0 hours until the next rotation, we want
+        // to rotate next hour. This is a special case.
+        return next_hour_timestamp(1)
     }
-    midnight_timestamp(days_until_next_rotation)
+    next_hour_timestamp(hours_until_next_rotation)
 }
 
 /// Calculate the time in milliseconds until the next_rotation, given
@@ -119,19 +119,19 @@ pub fn millis_until_next_rotation(next_rotation: u64) -> u64 {
 }
 
 /// Generate a deterministic genesis event corresponding to the DAG's configuration.
-pub fn generate_genesis(days_rotation: u64) -> Event {
-    // Days rotation is u64 except zero
-    let timestamp = if days_rotation == 0 {
+pub fn generate_genesis(hours_rotation: u64) -> Event {
+    // Hours rotation is u64 except zero
+    let timestamp = if hours_rotation == 0 {
         INITIAL_GENESIS
     } else {
-        // First check how many days passed since initial genesis.
-        let days_passed = days_since(INITIAL_GENESIS);
+        // First check how many hours passed since initial genesis.
+        let hours_passed = hours_since(INITIAL_GENESIS);
 
-        // Calculate the number of days_rotation intervals since INITIAL_GENESIS
-        let rotations_since_genesis = days_passed / days_rotation;
+        // Calculate the number of hours_rotation intervals since INITIAL_GENESIS
+        let rotations_since_genesis = hours_passed / hours_rotation;
 
         // Calculate the timestamp of the most recent event
-        INITIAL_GENESIS + (rotations_since_genesis * days_rotation * DAY as u64)
+        INITIAL_GENESIS + (rotations_since_genesis * hours_rotation * HOUR as u64)
     };
     let header = Header { timestamp, parents: [NULL_ID; N_EVENT_PARENTS], layer: 0 };
     Event { header, content: GENESIS_CONTENTS.to_vec() }
@@ -208,30 +208,30 @@ mod tests {
     use super::*;
 
     #[test]
-    fn test_days_since() {
-        let five_days_ago = midnight_timestamp(-5);
-        assert_eq!(days_since(five_days_ago), 5);
+    fn test_hours_since() {
+        let five_hours_ago = next_hour_timestamp(-5);
+        assert_eq!(hours_since(five_hours_ago), 5);
 
-        let today = midnight_timestamp(0);
-        assert_eq!(days_since(today), 0);
+        let this_hour = next_hour_timestamp(0);
+        assert_eq!(hours_since(this_hour), 0);
     }
 
     #[test]
     fn test_next_rotation_timestamp() {
-        let starting_point = midnight_timestamp(-10);
+        let starting_point = next_hour_timestamp(-10);
         let rotation_period = 7;
 
-        // The first rotation since the starting point would be 3 days ago.
-        // So the next rotation should be 4 days from now.
-        let expected = midnight_timestamp(4);
+        // The first rotation since the starting point would be 3 hours ago.
+        // So the next rotation should be 4 hours from now.
+        let expected = next_hour_timestamp(4);
         assert_eq!(next_rotation_timestamp(starting_point, rotation_period), expected);
 
-        // When starting from today with a rotation period of 1 (day),
-        // we should get tomorrow's timestamp.
+        // When starting from current hour with a rotation period of 1 (hour),
+        // we should get next hours's timestamp.
         // This is a special case.
-        let midnight_today: u64 = midnight_timestamp(0);
-        let midnight_tomorrow = midnight_today + 86_400_000u64; // add a day
-        assert_eq!(midnight_tomorrow, next_rotation_timestamp(midnight_today, 1));
+        let this_hour: u64 = next_hour_timestamp(0);
+        let next_hour = this_hour + 3_600_000u64; // add an hour
+        assert_eq!(next_hour, next_rotation_timestamp(this_hour, 1));
     }
 
     #[test]
@@ -248,10 +248,10 @@ mod tests {
 
     #[test]
     fn test_millis_until_next_rotation_is_within_rotation_interval() {
-        let days_rotation = 1u64;
+        let hours_rotation = 1u64;
         // The amount of time in seconds between rotations.
-        let rotation_interval = days_rotation * 86_400_000u64;
-        let next_rotation_timestamp = next_rotation_timestamp(INITIAL_GENESIS, days_rotation);
+        let rotation_interval = hours_rotation * 3_600_000u64;
+        let next_rotation_timestamp = next_rotation_timestamp(INITIAL_GENESIS, hours_rotation);
         let s = millis_until_next_rotation(next_rotation_timestamp);
         assert!(s < rotation_interval);
     }