event_graph: use millis for events timestamp, bump the versions of darkirc and taud and are changed slightly to accordigly interact with both old and new versions

This commit is contained in:
dasman
2024-09-15 15:27:31 +03:00
parent 0ada742edb
commit 75b18d684e
10 changed files with 111 additions and 34 deletions

4
Cargo.lock generated
View File

@@ -2208,7 +2208,7 @@ dependencies = [
[[package]]
name = "darkirc"
version = "0.5.0"
version = "0.5.1"
dependencies = [
"async-trait",
"bcrypt",
@@ -7091,7 +7091,7 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "taud"
version = "0.4.1"
version = "0.4.2"
dependencies = [
"async-trait",
"blake3 1.5.4",

View File

@@ -1,7 +1,7 @@
[package]
name = "darkirc"
description = "P2P IRC daemon"
version = "0.5.0"
version = "0.5.1"
edition = "2021"
authors = ["Dyne.org foundation <foundation@dyne.org>"]
license = "AGPL-3.0-only"

View File

@@ -190,7 +190,30 @@ impl Client {
}
// Otherwise, broadcast it
self.server.darkirc.p2p.broadcast(&EventPut(event)).await;
let self_version = self.server.darkirc.p2p.settings().read().await.app_version.clone();
let connected_peers = self.server.darkirc.p2p.hosts().peers();
let mut peers_with_matched_version = vec![];
let mut peers_with_different_version = vec![];
for peer in connected_peers {
let peer_version = peer.version.lock().await.clone();
if let Some(ref peer_version) = peer_version {
if self_version == peer_version.version {
peers_with_matched_version.push(peer)
} else {
peers_with_different_version.push(peer)
}
}
}
if !peers_with_matched_version.is_empty() {
self.server.darkirc.p2p.broadcast_to(&EventPut(event.clone()), &peers_with_matched_version).await;
}
if !peers_with_different_version.is_empty() {
let mut event = event;
event.timestamp /= 1000;
self.server.darkirc.p2p.broadcast_to(&EventPut(event), &peers_with_different_version).await;
}
// self.server.darkirc.p2p.broadcast(&EventPut(event)).await;
}
}
}

View File

@@ -1,7 +1,7 @@
[package]
name = "taud"
description = "Encrypted tasks management app using peer-to-peer network and Event Graph."
version = "0.4.1"
version = "0.4.2"
edition = "2021"
authors = ["Dyne.org foundation <foundation@dyne.org>"]
license = "AGPL-3.0-only"

View File

@@ -318,7 +318,30 @@ async fn start_sync_loop(
error!(target: "taud", "Failed inserting new event to DAG: {}", e);
} else {
// Otherwise, broadcast it
p2p.broadcast(&EventPut(event)).await;
let self_version = p2p.settings().read().await.app_version.clone();
let connected_peers = p2p.hosts().peers();
let mut peers_with_matched_version = vec![];
let mut peers_with_different_version = vec![];
for peer in connected_peers {
let peer_version = peer.version.lock().await.clone();
if let Some(ref peer_version) = peer_version {
if self_version == peer_version.version {
peers_with_matched_version.push(peer)
} else {
peers_with_different_version.push(peer)
}
}
}
if !peers_with_matched_version.is_empty() {
p2p.broadcast_to(&EventPut(event.clone()), &peers_with_matched_version).await;
}
if !peers_with_different_version.is_empty() {
let mut event = event;
event.timestamp /= 1000;
p2p.broadcast_to(&EventPut(event), &peers_with_different_version).await;
}
// p2p.broadcast(&EventPut(event)).await;
}
}
}

View File

@@ -49,13 +49,20 @@ impl Event {
/// of the codebase.
pub async fn new(data: Vec<u8>, event_graph: &EventGraph) -> Self {
let (layer, parents) = event_graph.get_next_layer_with_parents().await;
Self { timestamp: UNIX_EPOCH.elapsed().unwrap().as_secs(), content: data, parents, layer }
Self {
timestamp: UNIX_EPOCH.elapsed().unwrap().as_millis() as u64,
content: data,
parents,
layer,
}
}
/// Hash the [`Event`] to retrieve its ID
pub fn id(&self) -> blake3::Hash {
let mut hasher = blake3::Hasher::new();
self.timestamp.encode(&mut hasher).unwrap();
let timestamp =
if self.timestamp > 1e10 as u64 { self.timestamp / 1000 } else { self.timestamp };
timestamp.encode(&mut hasher).unwrap();
self.content.encode(&mut hasher).unwrap();
self.parents.encode(&mut hasher).unwrap();
self.layer.encode(&mut hasher).unwrap();
@@ -91,7 +98,7 @@ impl Event {
}
// Check if the event timestamp is after genesis timestamp
if self.timestamp < genesis_timestamp - EVENT_TIME_DRIFT {
if self.timestamp < genesis_timestamp - EVENT_TIME_DRIFT / 1000 {
return Ok(false)
}
@@ -99,7 +106,7 @@ impl Event {
// is after the next genesis timestamp
if days_rotation > 0 {
let next_genesis_timestamp = next_rotation_timestamp(INITIAL_GENESIS, days_rotation);
if self.timestamp > next_genesis_timestamp + EVENT_TIME_DRIFT {
if self.timestamp > next_genesis_timestamp + EVENT_TIME_DRIFT / 1000 {
return Ok(false)
}
}
@@ -159,19 +166,28 @@ impl Event {
/// assuming some possibility for a time drift.
/// Note: This validation does *NOT* check for recursive references(circles),
/// and should be used as a first quick check.
pub fn validate_new(&self) -> bool {
pub fn validate_new(&self, is_ver_match: bool) -> bool {
// Let's not bother with empty events
if self.content.is_empty() {
return false
}
// Check if the event is too old or too new
let now = UNIX_EPOCH.elapsed().unwrap().as_secs();
let too_old = self.timestamp < now - EVENT_TIME_DRIFT;
let too_new = self.timestamp > now + EVENT_TIME_DRIFT;
if too_old || too_new {
return false
if is_ver_match {
// Check if the event is too old or too new
let now = UNIX_EPOCH.elapsed().unwrap().as_millis() as u64;
let too_old = self.timestamp < now - EVENT_TIME_DRIFT;
let too_new = self.timestamp > now + EVENT_TIME_DRIFT;
if too_old || too_new {
return false
}
} else {
// Check if the event is too old or too new
let now = UNIX_EPOCH.elapsed().unwrap().as_secs();
let too_old = self.timestamp < (now - (EVENT_TIME_DRIFT / 1000));
let too_new = self.timestamp > (now + (EVENT_TIME_DRIFT / 1000));
if too_old || too_new {
return false
}
}
// Validate the parents. We have to check that at least one parent

View File

@@ -35,7 +35,7 @@ use tinyjson::JsonValue::{self};
use crate::{
event_graph::util::{replayer_log, seconds_until_next_rotation},
net::P2pPtr,
net::{channel::Channel, P2pPtr},
rpc::{
jsonrpc::{JsonResponse, JsonResult},
util::json_map,
@@ -66,16 +66,16 @@ use deg::DegEvent;
#[cfg(test)]
mod tests;
/// Initial genesis timestamp (07 Sep 2023, 00:00:00 UTC)
/// Initial genesis timestamp in millis (07 Sep 2023, 00:00:00 UTC)
/// Must always be UTC midnight.
const INITIAL_GENESIS: u64 = 1694044800;
const INITIAL_GENESIS: u64 = 1_694_044_800_000;
/// Genesis event contents
const GENESIS_CONTENTS: &[u8] = &[0x47, 0x45, 0x4e, 0x45, 0x53, 0x49, 0x53];
/// The number of parents an event is supposed to have.
const N_EVENT_PARENTS: usize = 5;
/// Allowed timestamp drift in seconds
const EVENT_TIME_DRIFT: u64 = 60;
/// Allowed timestamp drift in milliseconds
const EVENT_TIME_DRIFT: u64 = 60_000;
/// Null event ID
pub const NULL_ID: blake3::Hash = blake3::Hash::from_bytes([0x00; blake3::OUT_LEN]);
@@ -872,4 +872,18 @@ impl EventGraph {
Ok(result)
}
/// Check if the our version matches the connected peer's
/// return true if they are, false otherwise
async fn check_version_match(&self, channel: &Arc<Channel>) -> bool {
let self_version = self.p2p.settings().read().await.app_version.clone();
let peer_version = channel.version.lock().await.clone();
if let Some(ref peer_version) = peer_version {
if self_version == peer_version.version {
return true
}
}
false
}
}

View File

@@ -203,7 +203,8 @@ impl ProtocolEventGraph {
// Validate the new event first. If we do not consider it valid, we
// will just drop it and stay quiet. If the malicious threshold
// is reached, we will stop the connection.
if !event.validate_new() {
let is_ver_match = self.event_graph.check_version_match(&self.channel).await;
if !event.validate_new(is_ver_match) {
self.clone().increase_malicious_count().await?;
continue
}

View File

@@ -39,14 +39,14 @@ use crate::{
Result,
};
/// Seconds in a day
pub(super) const DAY: i64 = 86400;
/// MilliSeconds in a day
pub(super) const DAY: i64 = 86_400_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 {
// Get current time
let now = UNIX_EPOCH.elapsed().unwrap().as_secs() as i64;
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;
@@ -58,7 +58,7 @@ pub(super) fn midnight_timestamp(days: i64) -> u64 {
/// Calculate the number of days since a given midnight timestamp.
pub(super) fn days_since(midnight_ts: u64) -> u64 {
// Get current time
let now = UNIX_EPOCH.elapsed().unwrap().as_secs();
let now = UNIX_EPOCH.elapsed().unwrap().as_millis() as u64;
// Calculate the difference between the current timestamp
// and the given midnight timestamp
@@ -96,14 +96,14 @@ pub(super) fn next_rotation_timestamp(starting_timestamp: u64, rotation_period:
midnight_timestamp(days_until_next_rotation)
}
/// Calculate the time in seconds until the next_rotation, given
/// Calculate the time in milliseconds until the next_rotation, given
/// as a timestamp.
/// `next_rotation` here represents a timestamp in UNIX epoch format.
pub(super) fn seconds_until_next_rotation(next_rotation: u64) -> u64 {
// Store `now` in a variable in order to avoid a TOCTOU error.
// There may be a drift of one second between this panic check and
// the return value if we get unlucky.
let now = UNIX_EPOCH.elapsed().unwrap().as_secs();
let now = UNIX_EPOCH.elapsed().unwrap().as_millis() as u64;
if next_rotation < now {
panic!("Next rotation timestamp is in the past");
}
@@ -126,7 +126,7 @@ pub(super) fn generate_genesis(days_rotation: u64) -> Event {
INITIAL_GENESIS + (rotations_since_genesis * days_rotation * DAY as u64)
};
Event {
timestamp,
timestamp: timestamp / 1000, // to keep the genesis hash equal to old nodes.
content: GENESIS_CONTENTS.to_vec(),
parents: [NULL_ID; N_EVENT_PARENTS],
layer: 0,
@@ -225,7 +225,7 @@ mod tests {
// we should get tomorrow's timestamp.
// This is a special case.
let midnight_today: u64 = midnight_timestamp(0);
let midnight_tomorrow = midnight_today + 86400u64; // add a day, in seconds
let midnight_tomorrow = midnight_today + 86_400_000u64; // add a day, in milliseconds
assert_eq!(midnight_tomorrow, next_rotation_timestamp(midnight_today, 1));
}
@@ -245,7 +245,7 @@ mod tests {
fn test_seconds_until_next_rotation_is_within_rotation_interval() {
let days_rotation = 1u64;
// The amount of time in seconds between rotations.
let rotation_interval = days_rotation * 86400u64;
let rotation_interval = days_rotation * 86_400_000u64;
let next_rotation_timestamp = next_rotation_timestamp(INITIAL_GENESIS, days_rotation);
let s = seconds_until_next_rotation(next_rotation_timestamp);
assert!(s < rotation_interval);

View File

@@ -93,7 +93,7 @@ pub struct Channel {
/// The version message of the node we are connected to.
/// Some if the version exchange has already occurred, None
/// otherwise.
version: Mutex<Option<Arc<VersionMessage>>>,
pub version: Mutex<Option<Arc<VersionMessage>>>,
/// Channel debug info
pub info: ChannelInfo,
}