| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- use async_std::sync::{Arc, Mutex};
- use std::{
- collections::{HashMap, HashSet},
- fmt, io,
- };
- use async_executor::Executor;
- use async_recursion::async_recursion;
- use ripemd::{Digest, Ripemd256};
- use smol::future;
- use structopt::StructOpt;
- use structopt_toml::StructOptToml;
- use darkfi::{
- async_daemonize,
- util::{
- cli::{get_log_config, get_log_level, spawn_config},
- expand_path,
- path::get_config_path,
- serial::{Decodable, Encodable, ReadExt, SerialDecodable, SerialEncodable},
- },
- Result,
- };
- type EventId = [u8; 32];
- #[derive(SerialEncodable, SerialDecodable)]
- struct Event {
- previous_event_hash: EventId,
- action: EventAction,
- timestamp: u64,
- }
- impl Event {
- fn hash(&self) -> EventId {
- let mut bytes = Vec::new();
- self.encode(&mut bytes).expect("serialize failed!");
- let mut hasher = Ripemd256::new();
- hasher.update(bytes);
- let bytes = hasher.finalize().to_vec();
- let mut result = [0u8; 32];
- result.copy_from_slice(bytes.as_slice());
- result
- }
- }
- impl fmt::Debug for Event {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match &self.action {
- EventAction::PrivMsg(event) => {
- write!(f, "PRIVMSG {}: {} ({})", event.nick, event.msg, self.timestamp)
- }
- }
- }
- }
- enum EventAction {
- PrivMsg(PrivMsgEvent),
- }
- impl Encodable for EventAction {
- fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
- match self {
- Self::PrivMsg(event) => {
- let mut len = 0;
- len += 0u8.encode(&mut s)?;
- len += event.encode(s)?;
- Ok(len)
- }
- }
- }
- }
- impl Decodable for EventAction {
- fn decode<D: io::Read>(mut d: D) -> Result<Self> {
- let type_id = d.read_u8()?;
- match type_id {
- 0 => Ok(Self::PrivMsg(PrivMsgEvent::decode(d)?)),
- _ => Err(darkfi::Error::ParseFailed("Bad type ID byte for Event")),
- }
- }
- }
- #[derive(SerialEncodable, SerialDecodable)]
- struct PrivMsgEvent {
- nick: String,
- msg: String,
- }
- struct EventNode {
- // Only current root has this set to None
- parent: Option<EventNodePtr>,
- event: Event,
- children: Mutex<Vec<EventNodePtr>>,
- }
- type EventNodePtr = Arc<EventNode>;
- struct Model {
- // This is periodically updated so we discard old nodes
- current_root: EventId,
- orphans: Vec<Event>,
- event_map: HashMap<EventId, EventNodePtr>,
- }
- impl Model {
- fn new() -> Self {
- let root_node = Arc::new(EventNode {
- parent: None,
- event: Event {
- previous_event_hash: [0u8; 32],
- action: EventAction::PrivMsg(PrivMsgEvent {
- nick: "root".to_string(),
- msg: "Let there be dark".to_string(),
- }),
- timestamp: get_current_time(),
- },
- children: Mutex::new(Vec::new()),
- });
- let root_node_id = root_node.event.hash();
- let event_map = HashMap::from([(root_node_id.clone(), root_node)]);
- Self { current_root: root_node_id, orphans: Vec::new(), event_map }
- }
- async fn add(&mut self, event: Event) {
- self.orphans.push(event);
- self.reorganize().await;
- }
- // TODO: Update root only after some time
- // Recursively free nodes climbing up from old root to new root
- // Also remove entries from event_map
- async fn reorganize(&mut self) {
- let mut remaining_orphans = Vec::new();
- for orphan in std::mem::take(&mut self.orphans) {
- let prev_event = orphan.previous_event_hash.clone();
- // Parent does not yet exist
- if !self.event_map.contains_key(&prev_event) {
- remaining_orphans.push(orphan);
- // BIGTODO #1:
- // TODO: We need to fetch missing ancestors from the network
- // Trigger get_blocks() request
- continue
- }
- let parent = self.event_map.get(&prev_event).expect("logic error").clone();
- let node = Arc::new(EventNode {
- parent: Some(parent.clone()),
- event: orphan,
- children: Mutex::new(Vec::new()),
- });
- // BIGTODO #2:
- // Reject events which attach to forks too low in the chain
- // At some point we ignore all events from old branches
- //let depth = self.find_ancestor_depth(node.clone(), self.find_head().await);
- //if depth > 10 {
- // // Discard
- // continue
- //}
- parent.children.lock().await.push(node.clone());
- // Add node to the table
- self.event_map.insert(node.event.hash(), node);
- }
- }
- fn get_root(&self) -> EventNodePtr {
- let root_id = &self.current_root;
- return self.event_map.get(root_id).expect("root ID is not in the event map!").clone()
- }
- // find_head
- // -> recursively call itself
- // -> + 1 for every recursion, return self if no children
- // -> select max from returned values
- // Gets the lead node with the maximal number of events counting from root
- async fn find_head(&self) -> EventNodePtr {
- let root = self.get_root();
- Self::find_longest_chain(root, 0).await.1
- }
- #[async_recursion]
- async fn find_longest_chain(parent_node: EventNodePtr, i: u32) -> (u32, EventNodePtr) {
- let children = parent_node.children.lock().await;
- if children.is_empty() {
- return (i, parent_node.clone())
- }
- let mut current_max = 0;
- let mut current_node = None;
- for node in &*children {
- let (grandchild_i, grandchild_node) =
- Self::find_longest_chain(node.clone(), i + 1).await;
- if grandchild_i > current_max {
- current_max = grandchild_i;
- current_node = Some(grandchild_node.clone());
- } else if grandchild_i == current_max {
- // Break ties using the timestamp
- if grandchild_node.event.timestamp >
- current_node.as_ref().expect("current_node should be set!").event.timestamp
- {
- current_max = grandchild_i;
- current_node = Some(grandchild_node.clone());
- }
- }
- }
- assert_ne!(current_max, 0);
- (current_max, current_node.expect("internal logic error"))
- }
- fn find_height(&self, mut node: EventNodePtr) -> u32 {
- let mut height = 0;
- while node.event.hash() != self.current_root {
- height += 1;
- node = node.parent.as_ref().expect("non-root nodes should have a parent set").clone();
- }
- height
- }
- fn find_ancestor_depth(&self, mut node_a: EventNodePtr, mut node_b: EventNodePtr) -> u32 {
- let mut depth = 0;
- while node_a.event.hash() != node_b.event.hash() {
- depth += 1;
- node_a =
- node_a.parent.as_ref().expect("non-root nodes should have a parent set").clone();
- node_b =
- node_b.parent.as_ref().expect("non-root nodes should have a parent set").clone();
- }
- depth
- }
- async fn debug(&self) {
- for (event_id, event_node) in &self.event_map {
- let height = self.find_height(event_node.clone());
- println!("{}: {:?} [height={}]", hex::encode(&event_id), event_node.event, height);
- }
- println!("root: {}", hex::encode(&self.get_root().event.hash()));
- println!("head: {}", hex::encode(&self.find_head().await.event.hash()));
- }
- }
- pub const CONFIG_FILE: &str = "ircd_config.toml";
- pub const CONFIG_FILE_CONTENTS: &str = include_str!("../ircd_config.toml");
- #[derive(Clone, Debug, serde::Deserialize, StructOpt, StructOptToml)]
- #[serde(default)]
- #[structopt(name = "ircd")]
- pub struct Args {
- #[structopt(long)]
- pub config: Option<String>,
- /// Increase verbosity
- #[structopt(short, parse(from_occurrences))]
- pub verbose: u8,
- }
- fn get_current_time() -> u64 {
- let start = std::time::SystemTime::now();
- start
- .duration_since(std::time::UNIX_EPOCH)
- .expect("Time went backwards")
- .as_millis()
- .try_into()
- .unwrap()
- }
- fn create_message(previous_event_hash: EventId, nick: &str, msg: &str, timestamp: u64) -> Event {
- Event {
- previous_event_hash,
- action: EventAction::PrivMsg(PrivMsgEvent { nick: nick.to_string(), msg: msg.to_string() }),
- timestamp,
- }
- }
- struct View {
- seen: HashSet<EventId>,
- }
- impl View {
- pub fn new() -> Self {
- Self { seen: HashSet::new() }
- }
- fn process(_model: &Model) {
- // This does 2 passes:
- // 1. Walk down all chains and get unseen events
- // 2. Order those events according to timestamp
- // Then the events are replayed to the IRC client
- }
- }
- async_daemonize!(realmain);
- async fn realmain(_settings: Args, _executor: Arc<Executor<'_>>) -> Result<()> {
- let mut model = Model::new();
- let root_id = model.get_root().event.hash();
- let timestamp = get_current_time() + 1;
- let node1 = create_message(root_id, "alice", "alice message", timestamp);
- model.add(node1).await;
- let node2 = create_message(root_id, "bob", "bob message", timestamp);
- let node2_id = node2.hash();
- model.add(node2).await;
- let node3 = create_message(root_id, "charlie", "charlie message", timestamp);
- let node3_id = node3.hash();
- model.add(node3).await;
- let node4 = create_message(node2_id, "delta", "delta message", timestamp);
- let node4_id = node4.hash();
- model.add(node4).await;
- assert_eq!(model.find_head().await.event.hash(), node4_id);
- // Now lets extend another chain
- let node5 = create_message(node3_id, "epsilon", "epsilon message", timestamp);
- let node5_id = node5.hash();
- model.add(node5).await;
- let node6 = create_message(node5_id, "phi", "phi message", timestamp);
- let node6_id = node6.hash();
- model.add(node6).await;
- assert_eq!(model.find_head().await.event.hash(), node6_id);
- model.debug().await;
- Ok(())
- }
|