Explorar o código

bin: Delete ircd2

parazyd %!s(int64=3) %!d(string=hai) anos
pai
achega
6cd46d0adc

+ 0 - 44
bin/ircd2/Cargo.toml

@@ -1,44 +0,0 @@
-[package]
-name = "ircd2"
-description = "P2P IRC daemon"
-version = "0.4.0"
-edition = "2021"
-authors = ["Dyne.org foundation <foundation@dyne.org>"]
-license = "AGPL-3.0-only"
-homepage = "https://dark.fi"
-repository = "https://github.com/darkrenaissance/darkfi"
-
-[dependencies]
-darkfi = {path = "../../", features = ["net", "rpc", "bs58"]}
-darkfi-serial = {path = "../../src/serial"}
-
-# Async
-smol = "1.3.0"
-futures = "0.3.26"
-futures-rustls = "0.22.2"
-rustls-pemfile = "1.0.2"
-async-std = "1.12.0"
-async-trait = "0.1.64"
-easy-parallel = "3.2.0"
-
-# Crypto
-crypto_box = "0.8.2"
-rand = "0.8.5"
-
-# Misc
-clap = {version = "4.1.4", features = ["derive"]}
-log = "0.4.17"
-simplelog = "0.12.0"
-ctrlc = { version = "3.2.4", features = ["termination"] }
-url = "2.3.1"
-chrono = "0.4.23"
-ripemd = "0.1.3"
-
-# Encoding and parsing
-serde_json = "1.0.91"
-serde = {version = "1.0.152", features = ["derive"]}
-structopt = "0.3.26"
-structopt-toml = "0.5.1"
-bs58 = "0.4.0"
-toml = "0.7.1"
-hex = "0.4.3"

+ 0 - 4
bin/ircd2/README.md

@@ -1,4 +0,0 @@
-# ircd
-
-see [Darkfi Book](https://darkrenaissance.github.io/darkfi/misc/ircd.html) for the installation guide.
-

+ 0 - 33
bin/ircd2/config/inbound.toml

@@ -1,33 +0,0 @@
-## JSON-RPC listen URL
-rpc_listen="127.0.0.1:1234"
-
-## IRC listen URL
-irc_listen="127.0.0.1:11067"
-
-## Sets Datastore Path
-datastore="~/.config/ircd-inbound"
-
-## Raft net settings
-[net]
-## P2P accept addresses
-inbound=["127.0.0.1:11002"]
-
-## Connection slots
-#outbound_connections=5
-
-## P2P external addresses
-external_addr=["127.0.0.1:11004"]
-
-## Peers to connect to
-#peers=["127.0.0.1:11003"]
-
-## Seed nodes to connect to 
-seeds=["127.0.0.1:11001"]
-
-## these are the default configuration for the p2p network
-#manual_attempt_limit=0
-#seed_query_timeout_seconds=8
-#connect_timeout_seconds=10
-#channel_handshake_seconds=4
-#channel_heartbeat_seconds=10
-

+ 0 - 33
bin/ircd2/config/outbound.toml

@@ -1,33 +0,0 @@
-## JSON-RPC listen URL
-rpc_listen="127.0.0.1:7777"
-
-## IRC listen URL
-irc_listen="127.0.0.1:11066"
-
-## Sets Datastore Path
-datastore="~/.config/ircd-outbound"
-
-## Raft net settings
-[net]
-## P2P accept addresses
-# inbound=["127.0.0.1:11002"]
-
-## Connection slots
-outbound_connections=5
-
-## P2P external addresses
-#external_addr=["127.0.0.1:11002"]
-
-## Peers to connect to
-#peers=["127.0.0.1:11003"]
-
-## Seed nodes to connect to 
-seeds=["127.0.0.1:11001"]
-
-## these are the default configuration for the p2p network
-#manual_attempt_limit=0
-#seed_query_timeout_seconds=8
-#connect_timeout_seconds=10
-#channel_handshake_seconds=4
-#channel_heartbeat_seconds=10
-

+ 0 - 33
bin/ircd2/config/seed.toml

@@ -1,33 +0,0 @@
-## JSON-RPC listen URL
-rpc_listen="127.0.0.1:8000"
-
-## IRC listen URL
-irc_listen="127.0.0.1:11065"
-
-## Sets Datastore Path
-datastore="~/.config/ircd-seed"
-
-## Raft net settings
-[net]
-## P2P accept addresses
-inbound=["127.0.0.1:11001"]
-
-## Connection slots
-# outbound_connections=5
-
-## P2P external addresses
-# external_addr=["127.0.0.1:11001"]
-
-## Peers to connect to
-# peers=["127.0.0.1:11001"]
-
-## Seed nodes to connect to 
-# seeds=["127.0.0.1:11002"]
-
-## these are the default configuration for the p2p network
-#manual_attempt_limit=0
-#seed_query_timeout_seconds=8
-#connect_timeout_seconds=10
-#channel_handshake_seconds=4
-#channel_heartbeat_seconds=10
-

+ 0 - 84
bin/ircd2/ircd_config.toml

@@ -1,84 +0,0 @@
-## JSON-RPC listen URL
-#rpc_listen="tcp://127.0.0.1:25550"
-
-## IRC listen URL
-#irc_listen="tcp://127.0.0.1:6667"
-#irc_listen="tls://0.0.0.0:6697"
-
-## TLS certificate path if IRC acceptor uses TLS (optional)
-#irc_tls_cert = "/etc/letsencrypt/ircd/fullchain.pem"
-
-## TLS secret key path if IRC acceptor uses TLS (optional)
-#irc_tls_secret = "/etc/letsencrypt/ircd/privkey.pem"
-
-## List of channels to autojoin for new client connections
-autojoin = ["#dev", "#memes", "#philosophy", "#markets", "#math", "#random"]
-
-## Daemon specific password (optional, but once you configure it,
-## it is required from the client side)
-#password="CHANGE_ME"
-
-## P2P net settings
-[net]
-## Connection slots
-outbound_connections=5
-
-## P2P accept addresses
-#inbound = ["tls://0.0.0.0:25551"]
-# ipv6 version:
-#inbound = ["tls://[::]:25551"]
-
-## P2P external addresses
-## Put your IPs or hostnames here
-## This is how people can reach you on the inbound port configured above
-## You can also put an ipv6 address :)
-#external_addr = ["tls://XXX.XXX.XXX.XXX:25551"]
-# ipv6 version:
-#external_addr = ["tls://[ipv6 address here]:25551"]
-
-## Manually configured peers to connect to
-#peers = ["tls://127.0.0.1:25551"]
-
-## Seed nodes to connect to 
-seeds = ["tls://lilith0.dark.fi:25551", "tls://lilith1.dark.fi:25551"]
-
-# Prefered transports for outbound connections
-#outbound_transports = ["tls", "tcp"]
-
-## Only used for debugging. Compromises privacy when set.
-#node_id = "foo"
-
-## these are the default configuration for the p2p network
-#manual_attempt_limit=0
-#seed_query_timeout_seconds=8
-#connect_timeout_seconds=10
-#channel_handshake_seconds=4
-#channel_heartbeat_seconds=10
-
-## Per-channel settings
-#[channel."#foo"]
-## Create with `ircd --gen-secret`
-#secret = "7CkVuFgwTUpJn5Sv67Q3fyEDpa28yrSeL5Hg2GqQ4jfM"
-## Topic to set for the channel
-#topic = "DarkFi Foo Stuff"
-
-[channel."#dev"]
-topic = "DarkFi Development HQ"
-
-### Contacts list
-## Private key used to decrypt direct messages to you along with
-## contact_pubkey. (configured only once)
-## Generate keypair using 'ircd --gen-keypair' 
-## or to save to a file 'ircd --gen-keypair -o ~/some_dir/filename'
-## !!SHOULD NEVER SHARE THIS!!
-#[private_key."955Dfa83pU7RCevT2rMrGfhza4kcy6FShSNE6AdR4Q7A"]
-
-## Shared Public key that encrypt direct communication between two nicknames
-## on the network.
-## These are in the form of [Contact_nick, Contact_pubkey]
-## Per-contact settings
-## contact nickname (this is not irc nickname, and could be anything you want)
-## irc msgs should be pointed to this nickname.
-#[contact."narodnik"]
-## contact public key
-#contact_pubkey = "C9vC6HNDfGQofWCapZfQK5MkV1JR8Cct839RDUCqbDGK"

+ 0 - 18
bin/ircd2/script/README.md

@@ -1,18 +0,0 @@
-IRC Bots
-========
-
-## `meetbot`
-
-`meetbot.py` is a bot used to keep topics for IRC channels, that can
-be discussed on meetings. Multiple channels can be configured and this
-is done through `meetbot_cfg.py`.
-
-**Notes:**
-* Never add secrets to the public repo config!
-
-### Setup
-
-* Download `meetbot.py` and `meetbot_cfg.py` 
-* Edit `meetbot_cfg.py` for your needs.
-* Navigate terminal to the folder where `meetbot.py` is.
-* Run the bot: `$ python meetbot.py`

+ 0 - 249
bin/ircd2/script/meetbot.py

@@ -1,249 +0,0 @@
-#!/usr/bin/env python3
-import asyncio
-import logging
-import pickle
-
-from base58 import b58decode
-from nacl.public import PrivateKey, Box
-
-from meetbot_cfg import config
-
-# Initialized channels from the configuration
-CHANS = {}
-
-# Pickle DB
-PICKLE_DB = "meetbot.pickle"
-
-
-# TODO: while this is nice to support, it would perhaps be better to do it
-# all over the same connection rather than opening a socket for each channel.
-async def channel_listen(host, port, nick, chan):
-    try:
-        logging.info("%s: Connecting to %s:%s", chan, host, port)
-        reader, writer = await asyncio.open_connection(host, port)
-
-        logging.debug("%s: Send CAP msg", chan)
-        msg = "CAP REQ : no-history\r\n"
-        writer.write(msg.encode("utf-8"))
-        await writer.drain()
-
-        logging.debug("%s: Send NICK msg", chan)
-        msg = f"NICK {nick}\r\n"
-        writer.write(msg.encode("utf-8"))
-        await writer.drain()
-
-        logging.debug("%s: Send CAP END msg", chan)
-        msg = "CAP END\r\n"
-        writer.write(msg.encode("utf-8"))
-        await writer.drain()
-
-        logging.debug("%s: Send JOIN msg", chan)
-        msg = f"JOIN {chan}\r\n"
-        writer.write(msg.encode("utf-8"))
-        await writer.drain()
-
-        logging.info("%s: Listening to channel", chan)
-        while True:
-            msg = await reader.readline()
-            msg = msg.decode("utf8")
-            if not msg:
-                continue
-
-            split_msg = msg.split(" ")
-            command = split_msg[1]
-            nick_c = split_msg[0][1:].rsplit("!", 1)[0]
-            logging.debug("%s: Recv: %s", chan, msg.rstrip())
-
-            if command == "PRIVMSG":
-                msg_title = msg.split(" ")[3][1:].rstrip()
-                if not msg_title:
-                    logging.info("%s: Recv empty PRIVMSG, ignoring", chan)
-                    continue
-
-                if msg_title == "!start":
-                    logging.info("%s: Got !start", chan)
-                    topics = CHANS[chan]["topics"]
-                    reply = f"PRIVMSG {chan} :Meeting started"
-                    logging.info("%s: Send: %s", chan, reply)
-                    writer.write((reply + "\r\n").encode("utf-8"))
-                    await writer.drain()
-
-                    if len(topics) == 0:
-                        reply = f"PRIVMSG {chan} :No topics"
-                        logging.info("%s: Send: %s", chan, reply)
-                        writer.write((reply + "\r\n").encode("utf-8"))
-                        await writer.drain()
-                        continue
-
-                    reply = f"PRIVMSG {chan} :Topics:"
-                    logging.info("%s: Send: %s", chan, reply)
-                    writer.write((reply + "\r\n").encode("utf-8"))
-                    await writer.drain()
-
-                    for i, topic in enumerate(topics):
-                        reply = f"PRIVMSG {chan} :{i+1}. {topic}"
-                        logging.info("%s: Send: %s", chan, reply)
-                        writer.write((reply + "\r\n").encode("utf-8"))
-                        await writer.drain()
-
-                    cur_topic = topics.pop(0)
-                    reply = f"PRIVMSG {chan} :Current topic: {cur_topic}\r\n"
-                    CHANS[chan]["topics"] = topics
-                    writer.write(reply.encode("utf-8"))
-                    await writer.drain()
-                    continue
-
-                if msg_title == "!end":
-                    logging.info("%s: Got !end", chan)
-                    reply = f"PRIVMSG {chan} :Meeting ended"
-                    logging.info("%s: Send: %s", chan, reply)
-                    writer.write((reply + "\r\n").encode("utf-8"))
-                    await writer.drain()
-                    continue
-
-                if msg_title == "!topic":
-                    logging.info("%s: Got !topic", chan)
-                    topic = msg.split(" ", 4)
-
-                    if len(topic) != 5:
-                        logging.debug("%s: Topic msg len not 5, skipping",
-                                      chan)
-                        continue
-
-                    topic = topic[4].rstrip() + f" (by {nick_c})"
-
-                    if topic == "":
-                        logging.debug("%s: Topic message empty, skipping",
-                                      chan)
-                        continue
-
-                    topics = CHANS[chan]["topics"]
-                    if topic not in topics:
-                        topics.append(topic)
-                        CHANS[chan]["topics"] = topics
-                        logging.debug("%s: Appended topic to channel topics",
-                                      chan)
-                        reply = f"PRIVMSG {chan} :Added topic: {topic}"
-                        logging.info("%s: Send: %s", chan, reply)
-                    else:
-                        logging.debug("%s: Topic already in list of topics",
-                                      chan)
-                        reply = f"PRIVMSG {chan} :Topic already in list"
-                        logging.info("%s: Send: %s", chan, reply)
-
-                    writer.write((reply + "\r\n").encode("utf-8"))
-                    await writer.drain()
-                    continue
-
-                if msg_title == "!list":
-                    logging.info("%s: Got !list", chan)
-                    topics = CHANS[chan]["topics"]
-                    if len(topics) == 0:
-                        reply = f"PRIVMSG {chan} :No topics"
-                    else:
-                        reply = f"PRIVMSG {chan} :Topics:"
-
-                    logging.info("%s: Send: %s", chan, reply)
-                    writer.write((reply + "\r\n").encode("utf-8"))
-                    await writer.drain()
-
-                    for i, topic in enumerate(topics):
-                        reply = f"PRIVMSG {chan} :{i+1}. {topic}"
-                        logging.info("%s: Send: %s", chan, reply)
-                        writer.write((reply + "\r\n").encode("utf-8"))
-                        await writer.drain()
-
-                    continue
-
-                if msg_title == "!next":
-                    logging.info("%s: Got !next", chan)
-                    topics = CHANS[chan]["topics"]
-                    if len(topics) == 0:
-                        reply = f"PRIVMSG {chan} :No further topics"
-                    else:
-                        cur_topic = topics.pop(0)
-                        CHANS[chan]["topics"] = topics
-                        reply = f"PRIVMSG {chan} :Current topic: {cur_topic}"
-
-                    logging.info("%s: Send: %s", chan, reply)
-                    writer.write((reply + "\r\n").encode("utf-8"))
-                    await writer.drain()
-                    continue
-
-    except KeyboardInterrupt:
-        return
-    except ConnectionRefusedError:
-        logging.warning("%s: Connection refused, trying again in 3s...", chan)
-        await asyncio.sleep(3)
-        await channel_listen(host, port, nick, chan)
-    except Exception as e:
-        logging.error("EXCEPTION: %s", e)
-        logging.warn("%s: Connection interrupted. Reconnecting in 3s...", chan)
-        await asyncio.sleep(3)
-        await channel_listen(host, port, nick, chan)
-
-
-async def main(debug=False):
-    global CHANS
-
-    loglevel = logging.DEBUG if debug else logging.INFO
-    logfmt = "%(asctime)s [%(levelname)s]\t%(message)s"
-    logging.basicConfig(format=logfmt,
-                        level=loglevel,
-                        datefmt="%Y-%m-%d %H:%M:%S")
-
-    try:
-        with open(PICKLE_DB, "rb") as pickle_fd:
-            CHANS = pickle.load(pickle_fd)
-        logging.info("Loaded pickle database")
-    except:
-        logging.info("Did not find pickle database")
-
-    for i in config["channels"]:
-        name = i["name"]
-        logging.info("Found config for channel %s", name)
-
-        # TODO: This will be useful when ircd has a CAP that tells it to
-        # give **all** messages to the connected client, no matter if ircd
-        # itself has a configured secret or not.
-        # This way the ircd itself doesn't have to keep channel secrets, but
-        # they can rather only be held by this bot. In turn this means the bot
-        # can be deployed with any ircd.
-        if i["secret"]:
-            logging.info("Instantiating NaCl box for %s", name)
-            secret = b58decode(i["secret"].encode("utf-8"))
-            secret = PrivateKey(secret)
-            public = secret.public_key
-            box = Box(secret, public)
-        else:
-            box = None
-
-        if not CHANS.get(name):
-            CHANS[name] = {}
-
-        if not CHANS[name].get("topics"):
-            CHANS[name]["topics"] = []
-
-        CHANS[name]["box"] = box
-
-    coroutines = []
-    for i in CHANS.keys():
-        logging.debug("Creating async task for %s", i)
-        task = asyncio.create_task(
-            channel_listen(config["host"], config["port"], config["nick"], i))
-        coroutines.append(task)
-
-    await asyncio.gather(*coroutines)
-
-
-if __name__ == "__main__":
-    from sys import argv
-    DBG = bool(len(argv) == 2 and argv[1] == "-v")
-
-    try:
-        asyncio.run(main(debug=DBG))
-    except KeyboardInterrupt:
-        print("\rCaught ^C, saving pickle and exiting")
-
-    with open(PICKLE_DB, "wb") as fdesc:
-        pickle.dump(CHANS, fdesc, protocol=pickle.HIGHEST_PROTOCOL)

+ 0 - 23
bin/ircd2/script/meetbot_cfg.py

@@ -1,23 +0,0 @@
-config = {
-    # IRC server host
-    "host": "127.0.0.1",
-
-    # IRC server port
-    "port": 6667,
-
-    # IRC nickname
-    "nick": "meetbot",
-    "channels": [
-        {
-            "name": "#foo",
-            "secret": None,
-        },
-        {
-            "name": "#secret_channel",
-            # TODO: This is useless right now, but it would be nice
-            # to add a CAP in ircd to give all incoming PRIVMSG to be
-            # able to check them.
-            "secret": "HNEKcUmwsspdaL9b8sFn45b8Rf3bzv1LdYS1JVNvkPGL",
-        },
-    ],
-}

+ 0 - 139
bin/ircd2/src/crypto.rs

@@ -1,139 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::{collections::HashMap, fmt};
-
-use crypto_box::{
-    aead::{Aead, AeadCore},
-    SalsaBox,
-};
-use rand::rngs::OsRng;
-
-use crate::{
-    privmsg::PrivMsgEvent,
-    settings::{ChannelInfo, ContactInfo},
-};
-
-#[derive(serde::Serialize)]
-pub struct KeyPair {
-    pub private_key: String,
-    pub public_key: String,
-}
-
-impl fmt::Display for KeyPair {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "Public key: {}\nPrivate key: {}", self.public_key, self.private_key)
-    }
-}
-
-/// The format we're using is nonce+ciphertext, where nonce is 24 bytes.
-fn try_decrypt(salt_box: &SalsaBox, ciphertext: &str) -> Option<String> {
-    let bytes = match bs58::decode(ciphertext).into_vec() {
-        Ok(v) => v,
-        Err(_) => return None,
-    };
-
-    if bytes.len() < 25 {
-        return None
-    }
-
-    // Try extracting the nonce
-    let nonce = match bytes[0..24].try_into() {
-        Ok(v) => v,
-        Err(_) => return None,
-    };
-
-    // Take the remaining ciphertext
-    let message = &bytes[24..];
-
-    // Try decrypting the message
-    match salt_box.decrypt(nonce, message) {
-        Ok(v) => Some(String::from_utf8_lossy(&v).to_string()),
-        Err(_) => None,
-    }
-}
-
-/// The format we're using is nonce+ciphertext, where nonce is 24 bytes.
-pub fn encrypt(salt_box: &SalsaBox, plaintext: &str) -> String {
-    let nonce = SalsaBox::generate_nonce(&mut OsRng);
-    let mut ciphertext = salt_box.encrypt(&nonce, plaintext.as_bytes()).unwrap();
-
-    let mut concat = vec![];
-    concat.append(&mut nonce.as_slice().to_vec());
-    concat.append(&mut ciphertext);
-
-    bs58::encode(concat).into_string()
-}
-
-/// Decrypt PrivMsg target
-pub fn decrypt_target(
-    privmsg: &mut PrivMsgEvent,
-    configured_chans: &HashMap<String, ChannelInfo>,
-    configured_contacts: &HashMap<String, ContactInfo>,
-    private_key: &Option<String>,
-) {
-    for (name, chan_info) in configured_chans {
-        if !chan_info.joined {
-            continue
-        }
-
-        let salt_box = chan_info.salt_box(name).clone();
-
-        if let Some(salt_box) = salt_box {
-            if try_decrypt(&salt_box, &privmsg.target).is_some() {
-                privmsg.target = name.clone();
-                return
-            }
-        }
-    }
-
-    if private_key.is_none() {
-        return
-    }
-
-    for (name, contact_info) in configured_contacts {
-        let salt_box = contact_info.salt_box(private_key.as_ref().unwrap(), name).clone();
-
-        if let Some(salt_box) = salt_box {
-            if try_decrypt(&salt_box, &privmsg.target).is_some() {
-                privmsg.target = name.clone();
-                return
-            }
-        }
-    }
-}
-
-/// Decrypt PrivMsg nickname and message
-pub fn decrypt_privmsg(salt_box: &SalsaBox, privmsg: &mut PrivMsgEvent) {
-    let decrypted_nick = try_decrypt(salt_box, &privmsg.nick);
-    let decrypted_msg = try_decrypt(salt_box, &privmsg.msg);
-
-    if decrypted_nick.is_none() && decrypted_msg.is_none() {
-        return
-    }
-
-    privmsg.nick = decrypted_nick.unwrap();
-    privmsg.msg = decrypted_msg.unwrap();
-}
-
-/// Encrypt PrivMsg
-pub fn encrypt_privmsg(salt_box: &SalsaBox, privmsg: &mut PrivMsgEvent) {
-    privmsg.nick = encrypt(salt_box, &privmsg.nick);
-    privmsg.target = encrypt(salt_box, &privmsg.target);
-    privmsg.msg = encrypt(salt_box, &privmsg.msg);
-}

+ 0 - 42
bin/ircd2/src/events_queue.rs

@@ -1,42 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use async_std::sync::Arc;
-
-use darkfi::{Error, Result};
-
-use crate::model::Event;
-
-pub type EventsQueuePtr = Arc<EventsQueue>;
-
-pub struct EventsQueue(smol::channel::Sender<Event>, smol::channel::Receiver<Event>);
-
-impl EventsQueue {
-    pub fn new() -> EventsQueuePtr {
-        let (sn, rv) = smol::channel::unbounded();
-        Arc::new(Self(sn, rv))
-    }
-
-    pub async fn fetch(&self) -> Result<Event> {
-        self.1.recv().await.map_err(Error::from)
-    }
-
-    pub async fn dispatch(&self, event: &Event) -> Result<()> {
-        self.0.send(event.clone()).await.map_err(Error::from)
-    }
-}

+ 0 - 584
bin/ircd2/src/irc/client.rs

@@ -1,584 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::net::SocketAddr;
-
-use futures::{
-    io::{BufReader, ReadHalf, WriteHalf},
-    AsyncBufReadExt, AsyncRead, AsyncWrite, AsyncWriteExt, FutureExt,
-};
-
-use log::{debug, error, info, warn};
-
-use darkfi::{system::Subscription, Error, Result};
-
-use crate::{
-    crypto::{decrypt_privmsg, decrypt_target, encrypt_privmsg},
-    privmsg::PrivMsgEvent,
-    settings,
-    settings::RPL,
-    ChannelInfo,
-};
-
-use super::{ClientSubMsg, IrcConfig, NotifierMsg};
-
-pub struct IrcClient<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> {
-    // network stream
-    write_stream: WriteHalf<C>,
-    read_stream: BufReader<ReadHalf<C>>,
-    pub address: SocketAddr,
-
-    // irc config
-    irc_config: IrcConfig,
-
-    server_notifier: smol::channel::Sender<(NotifierMsg, u64)>,
-    subscription: Subscription<ClientSubMsg>,
-}
-
-impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcClient<C> {
-    pub fn new(
-        write_stream: WriteHalf<C>,
-        read_stream: BufReader<ReadHalf<C>>,
-        address: SocketAddr,
-        irc_config: IrcConfig,
-        server_notifier: smol::channel::Sender<(NotifierMsg, u64)>,
-        subscription: Subscription<ClientSubMsg>,
-    ) -> Self {
-        Self { write_stream, read_stream, address, irc_config, subscription, server_notifier }
-    }
-
-    /// Start listening for messages came from View or irc client
-    pub async fn listen(&mut self) {
-        loop {
-            let mut line = String::new();
-
-            futures::select! {
-                // Process msg from View
-                msg = self.subscription.receive().fuse() => {
-                    match msg {
-                        ClientSubMsg::Privmsg(mut m) => {
-                            if let Err(e) = self.process_msg(&mut m).await {
-                                error!("[CLIENT {}] Process msg: {}",  self.address, e);
-                                break
-                            }
-                        }
-                        ClientSubMsg::Config(c) => self.update_config(c).await,
-                    }
-
-                }
-                // Process msg from IRC client
-                err = self.read_stream.read_line(&mut line).fuse() => {
-                    if let Err(e) = err {
-                        error!("[CLIENT {}] Read line error: {}", self.address, e);
-                        break
-                    }
-                    if let Err(e) = self.process_line(line).await {
-                        error!("[CLIENT {}] Process line failed: {}",  self.address, e);
-                        break
-                    }
-                }
-            }
-        }
-
-        warn!("[CLIENT {}] Close connection", self.address);
-        self.subscription.unsubscribe().await;
-    }
-
-    pub async fn update_config(&mut self, new_config: IrcConfig) {
-        self.irc_config.channels.extend(new_config.channels);
-        self.irc_config.contacts.extend(new_config.contacts);
-        self.irc_config.nickname = new_config.nickname;
-        self.irc_config.private_key = new_config.private_key;
-        self.irc_config.password = new_config.password;
-
-        if self.on_receive_join(self.irc_config.channels.keys().cloned().collect()).await.is_err() {
-            warn!("Error to join updated channels");
-        }
-    }
-
-    pub async fn process_msg(&mut self, msg: &mut PrivMsgEvent) -> Result<()> {
-        info!("[CLIENT {}] msg from View: {:?}", self.address, msg.to_string());
-
-        decrypt_target(
-            msg,
-            &self.irc_config.channels,
-            &self.irc_config.contacts,
-            &self.irc_config.private_key,
-        );
-
-        if msg.target.starts_with('#') {
-            // Try to potentially decrypt the incoming message.
-            if !self.irc_config.channels.contains_key(&msg.target) {
-                return Ok(())
-            }
-
-            let chan_info = self.irc_config.channels.get_mut(&msg.target).unwrap();
-            if !chan_info.joined {
-                return Ok(())
-            }
-
-            if let Some(salt_box) = &chan_info.salt_box(&msg.target) {
-                decrypt_privmsg(salt_box, msg);
-                info!(
-                    "[CLIENT {}] Decrypted received message: {:?}",
-                    self.address,
-                    msg.to_string()
-                );
-            }
-
-            // add the nickname to the channel's names
-            if !chan_info.names.contains(&msg.nick) {
-                chan_info.names.push(msg.nick.clone());
-            }
-
-            self.reply(&msg.to_string()).await?;
-        } else if self.irc_config.private_key.is_some() {
-            if let Some(contact_info) = self.irc_config.contacts.get(&msg.target) {
-                let salt_box = &contact_info
-                    .salt_box(self.irc_config.private_key.as_ref().unwrap(), &msg.target);
-
-                if salt_box.is_none() {
-                    return Ok(())
-                }
-
-                decrypt_privmsg(salt_box.as_ref().unwrap(), msg);
-
-                info!(
-                    "[CLIENT {}] Decrypted received message: {:?}",
-                    self.address,
-                    msg.to_string()
-                );
-
-                self.reply(&msg.to_string()).await?;
-            }
-        }
-
-        Ok(())
-    }
-
-    pub async fn process_line(&mut self, line: String) -> Result<()> {
-        let irc_msg = match clean_input_line(line) {
-            Ok(msg) => msg,
-            Err(e) => {
-                warn!("[CLIENT {}] Connection error: {}", self.address, e);
-                return Err(Error::ChannelStopped)
-            }
-        };
-
-        info!("[CLIENT {}] Process msg: {}", self.address, irc_msg);
-
-        if let Err(e) = self.update(irc_msg).await {
-            warn!("[CLIENT {}] Connection error: {}", self.address, e);
-            return Err(Error::ChannelStopped)
-        }
-        Ok(())
-    }
-
-    async fn update(&mut self, line: String) -> Result<()> {
-        if line.len() > settings::MAXIMUM_LENGTH_OF_MESSAGE {
-            return Err(Error::MalformedPacket)
-        }
-
-        let (command, value) = parse_line(&line)?;
-        let (command, value) = (command.as_str(), value.as_str());
-
-        match command {
-            "PASS" => self.on_receive_pass(value).await?,
-            "USER" => self.on_receive_user().await?,
-            "NAMES" => self.on_receive_names(value.split(',').map(String::from).collect()).await?,
-            "NICK" => self.on_receive_nick(value).await?,
-            "JOIN" => self.on_receive_join(value.split(',').map(String::from).collect()).await?,
-            "PART" => self.on_receive_part(value.split(',').map(String::from).collect()).await?,
-            "TOPIC" => self.on_receive_topic(&line, value).await?,
-            "PING" => self.on_ping(value).await?,
-            "PRIVMSG" => self.on_receive_privmsg(&line, value).await?,
-            "CAP" => self.on_receive_cap(&line, &value.to_uppercase()).await?,
-            "QUIT" => self.on_quit()?,
-            _ => warn!("[CLIENT {}] Unimplemented `{}` command", self.address, command),
-        }
-
-        self.registre().await?;
-        Ok(())
-    }
-
-    async fn registre(&mut self) -> Result<()> {
-        if !self.irc_config.is_pass_init && self.irc_config.password.is_empty() {
-            self.irc_config.is_pass_init = true
-        }
-
-        if !self.irc_config.is_registered &&
-            self.irc_config.is_cap_end &&
-            self.irc_config.is_nick_init &&
-            self.irc_config.is_user_init
-        {
-            debug!("Initializing peer connection");
-            let register_reply =
-                format!(":darkfi 001 {} :Let there be dark\r\n", self.irc_config.nickname);
-            self.reply(&register_reply).await?;
-            self.irc_config.is_registered = true;
-
-            // join all channels
-            self.on_receive_join(self.irc_config.channels.keys().cloned().collect()).await?;
-
-            if *self.irc_config.capabilities.get("no-history").unwrap() {
-                return Ok(())
-            }
-        }
-        Ok(())
-    }
-
-    async fn reply(&mut self, message: &str) -> Result<()> {
-        self.write_stream.write_all(message.as_bytes()).await?;
-        debug!("Sent {}", message.trim_end());
-        Ok(())
-    }
-
-    fn on_quit(&self) -> Result<()> {
-        // Close the connection
-        Err(Error::NetworkServiceStopped)
-    }
-
-    async fn on_receive_user(&mut self) -> Result<()> {
-        // We can stuff any extra things like public keys in here.
-        // Ignore it for now.
-        if self.irc_config.is_pass_init {
-            self.irc_config.is_user_init = true;
-        } else {
-            // Close the connection
-            warn!("[CLIENT {}] Password is required", self.address);
-            return self.on_quit()
-        }
-        Ok(())
-    }
-
-    async fn on_receive_pass(&mut self, password: &str) -> Result<()> {
-        if self.irc_config.password == password {
-            self.irc_config.is_pass_init = true
-        } else {
-            // Close the connection
-            warn!("[CLIENT {}] Password is not correct!", self.address);
-            return self.on_quit()
-        }
-        Ok(())
-    }
-
-    async fn on_receive_nick(&mut self, nickname: &str) -> Result<()> {
-        if nickname.len() > settings::MAXIMUM_LENGTH_OF_NICKNAME {
-            return Ok(())
-        }
-
-        self.irc_config.is_nick_init = true;
-        let old_nick = std::mem::replace(&mut self.irc_config.nickname, nickname.to_string());
-
-        let nick_reply =
-            format!(":{}!anon@dark.fi NICK {}\r\n", old_nick, self.irc_config.nickname);
-        self.reply(&nick_reply).await
-    }
-
-    async fn on_receive_part(&mut self, channels: Vec<String>) -> Result<()> {
-        for chan in channels.iter() {
-            let part_reply =
-                format!(":{}!anon@dark.fi PART {}\r\n", self.irc_config.nickname, chan);
-            self.reply(&part_reply).await?;
-            if self.irc_config.channels.contains_key(chan) {
-                let chan_info = self.irc_config.channels.get_mut(chan).unwrap();
-                chan_info.joined = false;
-            }
-        }
-        Ok(())
-    }
-
-    async fn on_receive_topic(&mut self, line: &str, channel: &str) -> Result<()> {
-        if let Some(substr_idx) = line.find(':') {
-            // Client is setting the topic
-            if substr_idx >= line.len() {
-                return Err(Error::MalformedPacket)
-            }
-
-            let topic = &line[substr_idx + 1..];
-            let chan_info = self.irc_config.channels.get_mut(channel).unwrap();
-            chan_info.topic = Some(topic.to_string());
-
-            let topic_reply = format!(
-                ":{}!anon@dark.fi TOPIC {} :{}\r\n",
-                self.irc_config.nickname, channel, topic
-            );
-            self.reply(&topic_reply).await?;
-        } else {
-            // Client is asking or the topic
-            let chan_info = self.irc_config.channels.get(channel).unwrap();
-            let topic_reply = if let Some(topic) = &chan_info.topic {
-                format!(
-                    "{} {} {} :{}\r\n",
-                    RPL::Topic as u32,
-                    self.irc_config.nickname,
-                    channel,
-                    topic
-                )
-            } else {
-                const TOPIC: &str = "No topic is set";
-                format!(
-                    "{} {} {} :{}\r\n",
-                    RPL::NoTopic as u32,
-                    self.irc_config.nickname,
-                    channel,
-                    TOPIC
-                )
-            };
-            self.reply(&topic_reply).await?;
-        }
-        Ok(())
-    }
-
-    async fn on_ping(&mut self, value: &str) -> Result<()> {
-        let pong = format!("PONG {}\r\n", value);
-        self.reply(&pong).await
-    }
-
-    async fn on_receive_cap(&mut self, line: &str, subcommand: &str) -> Result<()> {
-        self.irc_config.is_cap_end = false;
-
-        let capabilities_keys: Vec<String> = self.irc_config.capabilities.keys().cloned().collect();
-
-        match subcommand {
-            "LS" => {
-                let cap_ls_reply = format!(
-                    ":{}!anon@dark.fi CAP * LS :{}\r\n",
-                    self.irc_config.nickname,
-                    capabilities_keys.join(" ")
-                );
-                self.reply(&cap_ls_reply).await?;
-            }
-
-            "REQ" => {
-                let substr_idx = line.find(':').ok_or(Error::MalformedPacket)?;
-
-                if substr_idx >= line.len() {
-                    return Err(Error::MalformedPacket)
-                }
-
-                let cap: Vec<&str> = line[substr_idx + 1..].split(' ').collect();
-
-                let mut ack_list = vec![];
-                let mut nak_list = vec![];
-
-                for c in cap {
-                    if self.irc_config.capabilities.contains_key(c) {
-                        self.irc_config.capabilities.insert(c.to_string(), true);
-                        ack_list.push(c);
-                    } else {
-                        nak_list.push(c);
-                    }
-                }
-
-                let cap_ack_reply = format!(
-                    ":{}!anon@dark.fi CAP * ACK :{}\r\n",
-                    self.irc_config.nickname,
-                    ack_list.join(" ")
-                );
-
-                let cap_nak_reply = format!(
-                    ":{}!anon@dark.fi CAP * NAK :{}\r\n",
-                    self.irc_config.nickname,
-                    nak_list.join(" ")
-                );
-
-                self.reply(&cap_ack_reply).await?;
-                self.reply(&cap_nak_reply).await?;
-            }
-
-            "LIST" => {
-                let enabled_capabilities: Vec<String> = self
-                    .irc_config
-                    .capabilities
-                    .clone()
-                    .into_iter()
-                    .filter(|(_, v)| *v)
-                    .map(|(k, _)| k)
-                    .collect();
-
-                let cap_list_reply = format!(
-                    ":{}!anon@dark.fi CAP * LIST :{}\r\n",
-                    self.irc_config.nickname,
-                    enabled_capabilities.join(" ")
-                );
-                self.reply(&cap_list_reply).await?;
-            }
-
-            "END" => {
-                self.irc_config.is_cap_end = true;
-            }
-            _ => {}
-        }
-        Ok(())
-    }
-
-    async fn on_receive_names(&mut self, channels: Vec<String>) -> Result<()> {
-        for chan in channels.iter() {
-            if !chan.starts_with('#') {
-                continue
-            }
-            if self.irc_config.channels.contains_key(chan) {
-                let chan_info = self.irc_config.channels.get(chan).unwrap();
-
-                if chan_info.names.is_empty() {
-                    return Ok(())
-                }
-
-                let names_reply = format!(
-                    ":{}!anon@dark.fi {} = {} : {}\r\n",
-                    self.irc_config.nickname,
-                    RPL::NameReply as u32,
-                    chan,
-                    chan_info.names.join(" ")
-                );
-
-                self.reply(&names_reply).await?;
-
-                let end_of_names = format!(
-                    ":DarkFi {:03} {} {} :End of NAMES list\r\n",
-                    RPL::EndOfNames as u32,
-                    self.irc_config.nickname,
-                    chan
-                );
-
-                self.reply(&end_of_names).await?;
-            }
-        }
-        Ok(())
-    }
-
-    async fn on_receive_privmsg(&mut self, line: &str, target: &str) -> Result<()> {
-        let substr_idx = line.find(':').ok_or(Error::MalformedPacket)?;
-
-        if substr_idx >= line.len() {
-            return Err(Error::MalformedPacket)
-        }
-
-        let message = line[substr_idx + 1..].to_string();
-
-        info!("[CLIENT {}] (Plain) PRIVMSG {} :{}", self.address, target, message,);
-
-        let mut privmsg = PrivMsgEvent {
-            nick: self.irc_config.nickname.clone(),
-            target: target.to_string(),
-            msg: message,
-        };
-
-        if target.starts_with('#') {
-            if !self.irc_config.channels.contains_key(target) {
-                return Ok(())
-            }
-
-            let channel_info = self.irc_config.channels.get(target).unwrap();
-
-            if !channel_info.joined {
-                return Ok(())
-            }
-
-            if let Some(salt_box) = &channel_info.salt_box(target) {
-                encrypt_privmsg(salt_box, &mut privmsg);
-                info!("[CLIENT {}] (Encrypted) PRIVMSG: {:?}", self.address, privmsg.to_string());
-            }
-        } else if self.irc_config.private_key.is_some() {
-            if let Some(contact_info) = self.irc_config.contacts.get(target) {
-                if let Some(salt_box) =
-                    &contact_info.salt_box(self.irc_config.private_key.as_ref().unwrap(), target)
-                {
-                    encrypt_privmsg(salt_box, &mut privmsg);
-                    info!(
-                        "[CLIENT {}] (Encrypted) PRIVMSG: {:?}",
-                        self.address,
-                        privmsg.to_string()
-                    );
-                }
-            }
-        }
-
-        self.server_notifier
-            .send((NotifierMsg::Privmsg(privmsg), self.subscription.get_id()))
-            .await?;
-
-        Ok(())
-    }
-
-    async fn on_receive_join(&mut self, channels: Vec<String>) -> Result<()> {
-        for chan in channels.iter() {
-            if !chan.starts_with('#') {
-                continue
-            }
-            if !self.irc_config.channels.contains_key(chan) {
-                let mut chan_info = ChannelInfo::new();
-                chan_info.topic = Some("n/a".to_string());
-                self.irc_config.channels.insert(chan.to_string(), chan_info);
-            }
-
-            let chan_info = self.irc_config.channels.get_mut(chan).unwrap();
-            if chan_info.joined {
-                return Ok(())
-            }
-            chan_info.joined = true;
-
-            let topic =
-                if let Some(topic) = chan_info.topic.clone() { topic } else { "n/a".to_string() };
-            chan_info.topic = Some(topic.to_string());
-
-            {
-                let j = format!(":{}!anon@dark.fi JOIN {}\r\n", self.irc_config.nickname, chan);
-                let t = format!(":DarkFi TOPIC {} :{}\r\n", chan, topic);
-                self.reply(&j).await?;
-                self.reply(&t).await?;
-            }
-        }
-        Ok(())
-    }
-}
-
-//
-// Helper functions
-//
-fn clean_input_line(mut line: String) -> Result<String> {
-    if line.is_empty() {
-        return Err(Error::ChannelStopped)
-    }
-
-    if line == "\n" || line == "\r\n" {
-        return Err(Error::ChannelStopped)
-    }
-
-    if &line[(line.len() - 2)..] == "\r\n" {
-        // Remove CRLF
-        line.pop();
-        line.pop();
-    } else if &line[(line.len() - 1)..] == "\n" {
-        line.pop();
-    } else {
-        return Err(Error::ChannelStopped)
-    }
-
-    Ok(line.clone())
-}
-
-fn parse_line(line: &str) -> Result<(String, String)> {
-    let mut tokens = line.split_ascii_whitespace();
-    // Commands can begin with :garbage but we will reject clients doing
-    // that for now to keep the protocol simple and focused.
-    let command = tokens.next().ok_or(Error::MalformedPacket)?.to_uppercase();
-    let value = tokens.next().ok_or(Error::MalformedPacket)?;
-    Ok((command, value.to_owned()))
-}

+ 0 - 272
bin/ircd2/src/irc/mod.rs

@@ -1,272 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::{collections::HashMap, fs::File, net::SocketAddr};
-
-use async_std::{net::TcpListener, sync::Arc};
-use futures::{io::BufReader, AsyncRead, AsyncReadExt, AsyncWrite};
-use futures_rustls::{rustls, TlsAcceptor};
-use log::{error, info};
-
-use darkfi::{system::SubscriberPtr, util::path::expand_path, Error, Result};
-
-use crate::{
-    privmsg::PrivMsgEvent,
-    settings::{Args, ChannelInfo, ContactInfo},
-};
-
-mod client;
-
-pub use client::IrcClient;
-
-#[derive(Clone)]
-pub struct IrcConfig {
-    // init bool
-    pub is_nick_init: bool,
-    pub is_user_init: bool,
-    pub is_registered: bool,
-    pub is_cap_end: bool,
-    pub is_pass_init: bool,
-
-    // user config
-    pub nickname: String,
-    pub password: String,
-    pub private_key: Option<String>,
-    pub capabilities: HashMap<String, bool>,
-
-    // channels and contacts
-    pub channels: HashMap<String, ChannelInfo>,
-    pub contacts: HashMap<String, ContactInfo>,
-}
-
-impl IrcConfig {
-    pub fn new(settings: &Args) -> Result<Self> {
-        let password = settings.password.as_ref().unwrap_or(&String::new()).clone();
-        let private_key = settings.private_key.clone();
-
-        let mut channels = settings.channels.clone();
-
-        for chan in settings.autojoin.iter() {
-            if !channels.contains_key(chan) {
-                channels.insert(chan.clone(), ChannelInfo::new());
-            }
-        }
-
-        let contacts = settings.contacts.clone();
-
-        let mut capabilities = HashMap::new();
-        capabilities.insert("no-history".to_string(), false);
-
-        Ok(Self {
-            is_nick_init: false,
-            is_user_init: false,
-            is_registered: false,
-            is_cap_end: true,
-            is_pass_init: false,
-            nickname: "anon".to_string(),
-            password,
-            channels,
-            contacts,
-            private_key,
-            capabilities,
-        })
-    }
-}
-
-#[derive(Clone)]
-pub enum ClientSubMsg {
-    Privmsg(PrivMsgEvent),
-    Config(IrcConfig),
-}
-#[derive(Clone)]
-pub enum NotifierMsg {
-    Privmsg(PrivMsgEvent),
-    UpdateConfig,
-}
-
-pub struct IrcServer {
-    settings: Args,
-    clients_subscriptions: SubscriberPtr<ClientSubMsg>,
-}
-
-impl IrcServer {
-    pub async fn new(
-        settings: Args,
-        clients_subscriptions: SubscriberPtr<ClientSubMsg>,
-    ) -> Result<Self> {
-        Ok(Self { settings, clients_subscriptions })
-    }
-    pub async fn start(&self, executor: Arc<smol::Executor<'_>>) -> Result<()> {
-        let (msg_notifier, msg_recv) = smol::channel::unbounded();
-
-        // Listen to msgs from clients
-        executor.spawn(Self::listen_to_msgs(msg_recv, self.clients_subscriptions.clone())).detach();
-
-        // Start listening for new connections
-        self.listen(msg_notifier, executor.clone()).await?;
-
-        Ok(())
-    }
-
-    /// Start listening to msgs from irc clients
-    pub async fn listen_to_msgs(
-        recv: smol::channel::Receiver<(NotifierMsg, u64)>,
-        clients_subscriptions: SubscriberPtr<ClientSubMsg>,
-    ) -> Result<()> {
-        loop {
-            let (msg, subscription_id) = recv.recv().await?;
-
-            match msg {
-                NotifierMsg::Privmsg(msg) => {
-                    // TODO Add to View to prevent duplicate msg, since a client may has already added the
-                    // msg to its buffer
-
-                    // Since this will be added to the View directly, other clients connected to irc
-                    // server must get informed about this new msg
-                    clients_subscriptions
-                        .notify_with_exclude(ClientSubMsg::Privmsg(msg), &[subscription_id])
-                        .await;
-
-                    // TODO broadcast to the p2p network
-                }
-
-                NotifierMsg::UpdateConfig => {
-                    //
-                    // load and parse the new settings from configuration file and pass it to all
-                    // irc clients
-                    //
-                    // let new_config = IrcConfig::new()?;
-                    // clients_subscriptions.notify(ClientSubMsg::Config(new_config)).await;
-                }
-            }
-        }
-    }
-
-    /// Start listening to new connections from irc clients
-    pub async fn listen(
-        &self,
-        notifier: smol::channel::Sender<(NotifierMsg, u64)>,
-        executor: Arc<smol::Executor<'_>>,
-    ) -> Result<()> {
-        let (listener, acceptor) = self.setup_listener().await?;
-        info!("[IRC SERVER] listening on {}", self.settings.irc_listen);
-
-        loop {
-            let (stream, peer_addr) = match listener.accept().await {
-                Ok((s, a)) => (s, a),
-                Err(e) => {
-                    error!("[IRC SERVER] Failed accepting new connections: {}", e);
-                    continue
-                }
-            };
-
-            let result = if let Some(acceptor) = acceptor.clone() {
-                // TLS connection
-                let stream = match acceptor.accept(stream).await {
-                    Ok(s) => s,
-                    Err(e) => {
-                        error!("[IRC SERVER] Failed accepting TLS connection: {}", e);
-                        continue
-                    }
-                };
-                self.process_connection(stream, peer_addr, notifier.clone(), executor.clone()).await
-            } else {
-                // TCP connection
-                self.process_connection(stream, peer_addr, notifier.clone(), executor.clone()).await
-            };
-
-            if let Err(e) = result {
-                error!("[IRC SERVER] Failed processing connection {}: {}", peer_addr, e);
-                continue
-            };
-
-            info!("[IRC SERVER] Accept new connection: {}", peer_addr);
-        }
-    }
-
-    /// On every new connection create new IrcClient
-    async fn process_connection<C: AsyncRead + AsyncWrite + Send + Unpin + 'static>(
-        &self,
-        stream: C,
-        peer_addr: SocketAddr,
-        notifier: smol::channel::Sender<(NotifierMsg, u64)>,
-        executor: Arc<smol::Executor<'_>>,
-    ) -> Result<()> {
-        let (reader, writer) = stream.split();
-        let reader = BufReader::new(reader);
-
-        // Subscription for the new client
-        let client_subscription = self.clients_subscriptions.clone().subscribe().await;
-
-        // new irc configuration
-        let irc_config = IrcConfig::new(&self.settings)?;
-
-        // New irc client
-        let mut client =
-            IrcClient::new(writer, reader, peer_addr, irc_config, notifier, client_subscription);
-
-        // Start listening and detach
-        executor
-            .spawn(async move {
-                client.listen().await;
-            })
-            .detach();
-
-        Ok(())
-    }
-
-    /// Setup a listener for irc server
-    async fn setup_listener(&self) -> Result<(TcpListener, Option<TlsAcceptor>)> {
-        let listenaddr = self.settings.irc_listen.socket_addrs(|| None)?[0];
-        let listener = TcpListener::bind(listenaddr).await?;
-
-        let acceptor = match self.settings.irc_listen.scheme() {
-            "tls" => {
-                // openssl genpkey -algorithm ED25519 > example.com.key
-                // openssl req -new -out example.com.csr -key example.com.key
-                // openssl x509 -req -days 700 -in example.com.csr -signkey example.com.key -out example.com.crt
-
-                if self.settings.irc_tls_secret.is_none() || self.settings.irc_tls_cert.is_none() {
-                    error!("[IRC SERVER] To listen using TLS, please set irc_tls_secret and irc_tls_cert in your config file.");
-                    return Err(Error::KeypairPathNotFound)
-                }
-
-                let file =
-                    File::open(expand_path(self.settings.irc_tls_secret.as_ref().unwrap())?)?;
-                let mut reader = std::io::BufReader::new(file);
-                let secret = &rustls_pemfile::pkcs8_private_keys(&mut reader)?[0];
-                let secret = rustls::PrivateKey(secret.clone());
-
-                let file = File::open(expand_path(self.settings.irc_tls_cert.as_ref().unwrap())?)?;
-                let mut reader = std::io::BufReader::new(file);
-                let certificate = &rustls_pemfile::certs(&mut reader)?[0];
-                let certificate = rustls::Certificate(certificate.clone());
-
-                let config = rustls::ServerConfig::builder()
-                    .with_safe_defaults()
-                    .with_no_client_auth()
-                    .with_single_cert(vec![certificate], secret)?;
-
-                let acceptor = TlsAcceptor::from(Arc::new(config));
-                Some(acceptor)
-            }
-            _ => None,
-        };
-        Ok((listener, acceptor))
-    }
-}

+ 0 - 161
bin/ircd2/src/main.rs

@@ -1,161 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use async_std::sync::{Arc, Mutex};
-use log::{info, warn};
-use rand::rngs::OsRng;
-use structopt_toml::StructOptToml;
-
-use darkfi::{
-    async_daemonize, net,
-    rpc::server::listen_and_serve,
-    system::Subscriber,
-    util::{file::save_json_file, path::expand_path},
-    Result,
-};
-
-pub mod crypto;
-pub mod events_queue;
-pub mod irc;
-pub mod model;
-pub mod privmsg;
-pub mod protocol_event;
-pub mod rpc;
-pub mod settings;
-pub mod view;
-
-use crate::{
-    crypto::KeyPair,
-    events_queue::EventsQueue,
-    irc::IrcServer,
-    model::Model,
-    protocol_event::{ProtocolEvent, Seen, UnreadEvents},
-    rpc::JsonRpcInterface,
-    settings::{Args, ChannelInfo, CONFIG_FILE, CONFIG_FILE_CONTENTS},
-    view::View,
-};
-
-async_daemonize!(realmain);
-async fn realmain(settings: Args, executor: Arc<smol::Executor<'_>>) -> Result<()> {
-    ////////////////////
-    // Generate new keypair and exit
-    ////////////////////
-    if settings.gen_keypair {
-        let secret_key = crypto_box::SecretKey::generate(&mut OsRng);
-        let pub_key = secret_key.public_key();
-        let prv_encoded = bs58::encode(secret_key.as_bytes()).into_string();
-        let pub_encoded = bs58::encode(pub_key.as_bytes()).into_string();
-
-        let kp = KeyPair { private_key: prv_encoded, public_key: pub_encoded };
-
-        if settings.output.is_some() {
-            let datastore = expand_path(&settings.output.unwrap())?;
-            save_json_file(&datastore, &kp)?;
-        } else {
-            println!("Generated KeyPair:\n{}", kp);
-        }
-
-        return Ok(())
-    }
-
-    ////////////////////
-    // Initialize the base structures
-    ////////////////////
-    let events_queue = EventsQueue::new();
-    let model = Arc::new(Mutex::new(Model::new(events_queue.clone())));
-    let _view = Arc::new(Mutex::new(View::new(events_queue)));
-
-    ////////////////////
-    // P2p setup
-    ////////////////////
-    // Buffers
-    let seen_event = Seen::new();
-    let seen_inv = Seen::new();
-    let unread_events = UnreadEvents::new();
-
-    // Check the version
-    let mut net_settings = settings.net.clone();
-    net_settings.app_version = Some(option_env!("CARGO_PKG_VERSION").unwrap_or("").to_string());
-
-    // New p2p
-    let p2p = net::P2p::new(net_settings.into()).await;
-    let p2p2 = p2p.clone();
-
-    // Register the protocol_event
-    let registry = p2p.protocol_registry();
-    registry
-        .register(net::SESSION_ALL, move |channel, p2p| {
-            let seen_event = seen_event.clone();
-            let seen_inv = seen_inv.clone();
-            let model = model.clone();
-            let unread_events = unread_events.clone();
-            async move {
-                ProtocolEvent::init(channel, p2p, model, seen_event, seen_inv, unread_events).await
-            }
-        })
-        .await;
-
-    // Start
-    p2p.clone().start(executor.clone()).await?;
-
-    // Run
-    let executor_cloned = executor.clone();
-    executor_cloned.spawn(p2p.clone().run(executor.clone())).detach();
-
-    ////////////////////
-    // RPC interface setup
-    ////////////////////
-    let rpc_listen_addr = settings.rpc_listen.clone();
-    let rpc_interface =
-        Arc::new(JsonRpcInterface { addr: rpc_listen_addr.clone(), p2p: p2p.clone() });
-    let _ex = executor.clone();
-    executor
-        .spawn(async move { listen_and_serve(rpc_listen_addr, rpc_interface, _ex).await })
-        .detach();
-
-    ////////////////////
-    // IRC server
-    ////////////////////
-    let clients_subscriptions = Subscriber::new();
-
-    // New irc server
-    let irc_server = IrcServer::new(settings.clone(), clients_subscriptions).await?;
-
-    // Start the irc server and detach it
-    let executor_cloned = executor.clone();
-    executor_cloned.spawn(async move { irc_server.start(executor.clone()).await }).detach();
-
-    ////////////////////
-    // Wait for SIGINT
-    ////////////////////
-    let (signal, shutdown) = smol::channel::bounded::<()>(1);
-    ctrlc::set_handler(move || {
-        warn!(target: "ircd", "ircd start Exit Signal");
-        // cleaning up tasks running in the background
-        async_std::task::block_on(signal.send(())).unwrap();
-    })
-    .unwrap();
-
-    shutdown.recv().await?;
-    print!("\r");
-    info!("Caught termination signal, cleaning up and exiting...");
-
-    // stop p2p
-    p2p2.stop().await;
-    Ok(())
-}

+ 0 - 613
bin/ircd2/src/model.rs

@@ -1,613 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::{cmp::Ordering, collections::HashMap, fmt};
-
-use async_std::sync::{Arc, Mutex};
-use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable};
-use ripemd::{Digest, Ripemd256};
-
-use crate::{
-    events_queue::EventsQueuePtr,
-    privmsg::{EventAction, PrivMsgEvent},
-    settings::get_current_time,
-};
-
-pub type EventId = [u8; 32];
-
-const MAX_DEPTH: u32 = 300;
-const MAX_HEIGHT: u32 = 300;
-
-#[derive(SerialEncodable, SerialDecodable, Clone)]
-pub struct Event {
-    previous_event_hash: EventId,
-    action: EventAction,
-    pub timestamp: u64,
-    #[skip_serialize]
-    pub read_confirms: u8,
-}
-
-impl Event {
-    pub 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)
-            }
-        }
-    }
-}
-
-#[derive(Debug, Clone)]
-struct EventNode {
-    // Only current root has this set to None
-    parent: Option<EventId>,
-    event: Event,
-    children: Vec<EventId>,
-}
-
-pub type ModelPtr = Arc<Mutex<Model>>;
-
-pub struct Model {
-    // This is periodically updated so we discard old nodes
-    current_root: EventId,
-    orphans: HashMap<EventId, Event>,
-    event_map: HashMap<EventId, EventNode>,
-    _events_queue: EventsQueuePtr,
-}
-
-impl Model {
-    pub fn new(events_queue: EventsQueuePtr) -> Self {
-        let root_node = 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(),
-                    target: "root".to_string(),
-                }),
-                timestamp: get_current_time(),
-                read_confirms: 0,
-            },
-            children: Vec::new(),
-        };
-
-        let root_node_id = root_node.event.hash();
-
-        let mut event_map = HashMap::new();
-        event_map.insert(root_node_id, root_node);
-
-        Self {
-            current_root: root_node_id,
-            orphans: HashMap::new(),
-            event_map,
-            _events_queue: events_queue,
-        }
-    }
-
-    pub fn add(&mut self, event: Event) {
-        self.orphans.insert(event.hash(), event);
-        self.reorganize();
-    }
-
-    pub fn is_orphan(&self, event: &Event) -> bool {
-        !self.event_map.contains_key(&event.previous_event_hash)
-    }
-
-    pub fn find_leaves(&self) -> Vec<EventId> {
-        // collect the leaves in the tree
-        let mut leaves = vec![];
-
-        for (event_hash, node) in self.event_map.iter() {
-            // check if the node is a leaf
-            if node.children.is_empty() {
-                leaves.push(*event_hash);
-            }
-        }
-
-        leaves
-    }
-
-    pub fn get_event(&self, event: &EventId) -> Option<Event> {
-        self.event_map.get(event).map(|en| en.event.clone())
-    }
-
-    pub fn get_event_children(&self, event: &EventId) -> Vec<Event> {
-        let mut children = vec![];
-        if let Some(ev) = self.event_map.get(event) {
-            for child in ev.children.iter() {
-                let child = self.event_map.get(child).unwrap();
-                children.push(child.event.clone());
-            }
-        }
-        children
-    }
-
-    fn reorganize(&mut self) {
-        for (_, orphan) in std::mem::take(&mut self.orphans) {
-            if self.is_orphan(&orphan) {
-                // TODO should we remove orphan if it's too old
-                continue
-            }
-
-            let prev_event = orphan.previous_event_hash;
-
-            let node =
-                EventNode { parent: Some(prev_event), event: orphan.clone(), children: Vec::new() };
-            let node_hash = node.event.hash();
-
-            let parent = self.event_map.get_mut(&prev_event).unwrap();
-            parent.children.push(node_hash);
-
-            self.event_map.insert(node_hash, node);
-
-            // TODO dispatch to events_queue
-            // to use events_queue here the add() and reorganize() functions should change to async
-
-            // clean up the tree from old eventnodes
-            self.prune_chains();
-            self.update_root();
-        }
-    }
-
-    fn prune_chains(&mut self) {
-        let head = self.find_head();
-        let leaves = self.find_leaves();
-
-        // Reject events which attach to chains too low in the chain
-        // At some point we ignore all events from old branches
-        for leaf in leaves {
-            // skip the head event
-            if leaf == head {
-                continue
-            }
-
-            let depth = self.diff_depth(leaf, head);
-            if depth > MAX_DEPTH {
-                self.remove_node(leaf);
-            }
-        }
-    }
-
-    fn update_root(&mut self) {
-        let head = self.find_head();
-        let leaves = self.find_leaves();
-
-        // find the common ancestor for each leaf and the head event
-        let mut ancestors = vec![];
-        for leaf in leaves {
-            if leaf == head {
-                continue
-            }
-
-            let ancestor = self.find_ancestor(leaf, head);
-            ancestors.push(ancestor);
-        }
-
-        // find the highest ancestor
-        let highest_ancestor = ancestors
-            .iter()
-            .max_by(|&a, &b| self.find_depth(*a, &head).cmp(&self.find_depth(*b, &head)));
-
-        // set the new root
-        if let Some(ancestor) = highest_ancestor {
-            // the ancestor must have at least height > MAX_HEIGHT
-            let ancestor_height = self.find_height(&self.current_root, ancestor).unwrap();
-            if ancestor_height < MAX_HEIGHT {
-                return
-            }
-
-            // removing the parents of the new root node
-            let mut root = self.event_map.get(&self.current_root).unwrap();
-            loop {
-                let root_hash = root.event.hash();
-
-                if &root_hash == ancestor {
-                    break
-                }
-
-                let root_childs = &root.children;
-                assert_eq!(root_childs.len(), 1);
-                let child = *root_childs.first().unwrap();
-
-                self.event_map.remove(&root_hash);
-                root = self.event_map.get(&child).unwrap();
-            }
-
-            self.current_root = *ancestor;
-        }
-    }
-
-    fn remove_node(&mut self, mut event_id: EventId) {
-        loop {
-            if !self.event_map.contains_key(&event_id) {
-                break
-            }
-
-            let node = self.event_map.get(&event_id).unwrap().clone();
-            self.event_map.remove(&event_id);
-
-            let parent = self.event_map.get_mut(&node.parent.unwrap()).unwrap();
-            let index = parent.children.iter().position(|&n| n == event_id).unwrap();
-            parent.children.remove(index);
-
-            if !parent.children.is_empty() {
-                break
-            }
-            event_id = parent.event.hash();
-        }
-    }
-
-    // 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
-    fn find_head(&self) -> EventId {
-        self.find_longest_chain(&self.current_root, 0).0
-    }
-
-    fn find_longest_chain(&self, parent_node: &EventId, i: u32) -> (EventId, u32) {
-        let children = &self.event_map.get(parent_node).unwrap().children;
-        if children.is_empty() {
-            return (*parent_node, i)
-        }
-
-        let mut current_max = 0;
-        let mut current_node = None;
-        for node in children.iter() {
-            let (grandchild_node, grandchild_i) = self.find_longest_chain(node, i + 1);
-
-            match &grandchild_i.cmp(&current_max) {
-                Ordering::Greater => {
-                    current_max = grandchild_i;
-                    current_node = Some(grandchild_node);
-                }
-                Ordering::Equal => {
-                    // Break ties using the timestamp
-                    let grandchild_node_timestamp =
-                        self.event_map.get(&grandchild_node).unwrap().event.timestamp;
-                    let current_node_timestamp =
-                        self.event_map.get(&current_node.unwrap()).unwrap().event.timestamp;
-
-                    if grandchild_node_timestamp > current_node_timestamp {
-                        current_max = grandchild_i;
-                        current_node = Some(grandchild_node);
-                    }
-                }
-                Ordering::Less => {
-                    // Left a todo here, not sure if it should be handled
-                    todo!();
-                }
-            }
-        }
-        assert_ne!(current_max, 0);
-        (current_node.expect("internal logic error"), current_max)
-    }
-
-    fn find_depth(&self, mut node: EventId, ancestor_id: &EventId) -> u32 {
-        let mut depth = 0;
-        while &node != ancestor_id {
-            depth += 1;
-            if let Some(parent) = self.event_map.get(&node).unwrap().parent {
-                node = parent
-            } else {
-                break
-            }
-        }
-        depth
-    }
-
-    fn find_height(&self, node: &EventId, child_id: &EventId) -> Option<u32> {
-        let mut height = 0;
-
-        if node == child_id {
-            return Some(height)
-        }
-        height += 1;
-        let children = &self.event_map.get(node).unwrap().children;
-        if children.is_empty() {
-            return None
-        }
-
-        for child in children.iter() {
-            if let Some(h) = self.find_height(child, child_id) {
-                return Some(height + h)
-            }
-        }
-        None
-    }
-
-    fn find_ancestor(&self, mut node_a: EventId, mut node_b: EventId) -> EventId {
-        // node_a is a child of node_b
-        let is_child = node_b == self.event_map.get(&node_a).unwrap().parent.unwrap();
-
-        if is_child {
-            return node_b
-        }
-
-        while node_a != node_b {
-            let node_a_parent = self.event_map.get(&node_a).unwrap().parent.unwrap();
-            let node_b_parent = self.event_map.get(&node_b).unwrap().parent.unwrap();
-
-            if node_a_parent == self.current_root || node_b_parent == self.current_root {
-                return self.current_root
-            }
-
-            node_a = node_a_parent;
-            node_b = node_b_parent;
-        }
-
-        node_a
-    }
-
-    fn diff_depth(&self, node_a: EventId, node_b: EventId) -> u32 {
-        let ancestor = self.find_ancestor(node_a, node_b);
-        let node_a_depth = self.find_depth(node_a, &ancestor);
-        let node_b_depth = self.find_depth(node_b, &ancestor);
-
-        (node_b_depth + 1) - node_a_depth
-    }
-
-    fn _debug(&self) {
-        for (event_id, event_node) in &self.event_map {
-            let depth = self.find_depth(*event_id, &self.current_root);
-            println!("{}: {:?} [depth={}]", hex::encode(event_id), event_node.event, depth);
-        }
-
-        println!("root: {}", hex::encode(self.current_root));
-        println!("head: {}", hex::encode(self.find_head()));
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::events_queue::EventsQueue;
-
-    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(),
-                target: "".to_string(),
-            }),
-            timestamp,
-            read_confirms: 4,
-        }
-    }
-
-    /* THIS IS FAILING
-    #[test]
-    fn test_update_root() {
-        let events_queue = EventsQueue::new();
-        let mut model = Model::new(events_queue);
-        let root_id = model.current_root;
-
-        // event_node 1
-        // Fill this node with MAX_HEIGHT events
-        let mut id1 = root_id;
-        for x in 0..MAX_HEIGHT {
-            let timestamp = get_current_time() + 1;
-            let node = create_message(id1, &format!("chain 1 msg {}", x), "message", timestamp);
-            id1 = node.hash();
-            model.add(node);
-        }
-
-        // event_node 2
-        // Fill this node with MAX_HEIGHT + 10 events
-        let mut id2 = root_id;
-        for x in 0..(MAX_HEIGHT + 10) {
-            let timestamp = get_current_time() + 1;
-            let node = create_message(id2, &format!("chain 2 msg {}", x), "message", timestamp);
-            id2 = node.hash();
-            model.add(node);
-        }
-
-        // Fill id2 node with MAX_HEIGHT / 2
-        let mut id3 = id2;
-        for x in (MAX_HEIGHT + 10)..(MAX_HEIGHT * 2) {
-            let timestamp = get_current_time() + 1;
-            let node =
-                create_message(id3, &format!("chain 2 branch 1 msg {}", x), "message", timestamp);
-            id3 = node.hash();
-            model.add(node);
-        }
-
-        // Fill id2 node with 9 events
-        let mut id4 = id2;
-        for x in (MAX_HEIGHT + 10)..(MAX_HEIGHT * 2 + 30) {
-            let timestamp = get_current_time() + 1;
-            let node =
-                create_message(id4, &format!("chain 2 branch 2 msg {}", x), "message", timestamp);
-            id4 = node.hash();
-            model.add(node);
-        }
-
-        assert_eq!(model.find_height(&model.current_root, &id2).unwrap(), 0);
-        assert_eq!(model.find_height(&model.current_root, &id3).unwrap(), (MAX_HEIGHT - 10));
-        assert_eq!(model.find_height(&model.current_root, &id4).unwrap(), (MAX_HEIGHT + 20));
-        assert_eq!(model.current_root, id2);
-    }
-
-    #[test]
-    fn test_find_height() {
-        let events_queue = EventsQueue::new();
-        let mut model = Model::new(events_queue);
-        let root_id = model.current_root;
-
-        // event_node 1
-        // Fill this node with 8 events
-        let mut id1 = root_id;
-        for x in 0..8 {
-            let timestamp = get_current_time() + 1;
-            let node = create_message(id1, &format!("chain 1 msg {}", x), "message", timestamp);
-            id1 = node.hash();
-            model.add(node);
-        }
-
-        // event_node 2
-        // Fill this node with 14 events
-        let mut id2 = root_id;
-        for x in 0..14 {
-            let timestamp = get_current_time() + 1;
-            let node = create_message(id2, &format!("chain 2 msg {}", x), "message", timestamp);
-            id2 = node.hash();
-            model.add(node);
-        }
-
-        assert_eq!(model.find_height(&model.current_root, &id1).unwrap(), 8);
-        assert_eq!(model.find_height(&model.current_root, &id2).unwrap(), 14);
-    }
-
-    #[test]
-    fn test_prune_chains() {
-        let events_queue = EventsQueue::new();
-        let mut model = Model::new(events_queue);
-        let root_id = model.current_root;
-
-        // event_node 1
-        // Fill this node with 3 events
-        let mut event_node_1_ids = vec![];
-        let mut id1 = root_id;
-        for x in 0..3 {
-            let timestamp = get_current_time() + 1;
-            let node = create_message(id1, &format!("chain 1 msg {}", x), "message", timestamp);
-            id1 = node.hash();
-            model.add(node);
-            event_node_1_ids.push(id1);
-        }
-
-        // event_node 2
-        // Start from the root_id and fill the node with 14 events
-        // All the events from event_node_1 should get removed from the tree
-        let mut id2 = root_id;
-        for x in 0..(MAX_DEPTH + 10) {
-            let timestamp = get_current_time() + 1;
-            let node = create_message(id2, &format!("chain 2 msg {}", x), "message", timestamp);
-            id2 = node.hash();
-            model.add(node);
-        }
-
-        assert_eq!(model.find_head(), id2);
-
-        for id in event_node_1_ids {
-            assert!(!model.event_map.contains_key(&id));
-        }
-
-        assert_eq!(model.event_map.len(), (MAX_DEPTH + 11) as usize);
-    }
-
-    #[test]
-    fn test_diff_depth() {
-        let events_queue = EventsQueue::new();
-        let mut model = Model::new(events_queue);
-        let root_id = model.current_root;
-
-        // event_node 1
-        // Fill this node with (MAX_DEPTH / 2) events
-        let mut id1 = root_id;
-        for x in 0..(MAX_DEPTH / 2) {
-            let timestamp = get_current_time() + 1;
-            let node = create_message(id1, &format!("chain 1 msg {}", x), "message", timestamp);
-            id1 = node.hash();
-            model.add(node);
-        }
-
-        // event_node 2
-        // Start from the root_id and fill the node with (MAX_DEPTH + 10) events
-        // all the events must be added since the depth between id1
-        // and the last head is less than MAX_DEPTH
-        let mut id2 = root_id;
-        for x in 0..(MAX_DEPTH + 10) {
-            let timestamp = get_current_time() + 1;
-            let node = create_message(id2, &format!("chain 2 msg {}", x), "message", timestamp);
-            id2 = node.hash();
-            model.add(node);
-        }
-
-        assert_eq!(model.find_head(), id2);
-
-        // event_node 3
-        // This will start as new chain, but no events will be added
-        // since the last event's depth is MAX_DEPTH + 10
-        let mut id3 = root_id;
-        for x in 0..30 {
-            let timestamp = get_current_time() + 1;
-            let node = create_message(id3, &format!("chain 3 msg {}", x), "message", timestamp);
-            id3 = node.hash();
-            model.add(node);
-
-            // ensure events are not added
-            assert!(!model.event_map.contains_key(&id3));
-        }
-
-        assert_eq!(model.find_head(), id2);
-
-        // Add more events to the event_node 1
-        // At the end this chain must overtake the event_node 2
-        for x in (MAX_DEPTH / 2)..(MAX_DEPTH + 15) {
-            let timestamp = get_current_time() + 1;
-            let node = create_message(id1, &format!("chain 1 msg {}", x), "message", timestamp);
-            id1 = node.hash();
-            model.add(node);
-        }
-
-        assert_eq!(model.find_head(), id1);
-    }
-    */
-
-    #[test]
-    fn test_event_hash() {
-        let events_queue = EventsQueue::new();
-        let model = Model::new(events_queue);
-        let root_id = model.current_root;
-
-        let timestamp = get_current_time() + 1;
-        let event = create_message(root_id, "msg", "message", timestamp);
-        let mut event2 = event.clone();
-
-        let event_hash = event.hash();
-
-        event2.read_confirms += 3;
-        let event2_hash = event2.hash();
-
-        assert_eq!(event2_hash, event_hash);
-        assert_ne!(event2.read_confirms, event.read_confirms);
-    }
-}

+ 0 - 62
bin/ircd2/src/privmsg.rs

@@ -1,62 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::io;
-
-use darkfi_serial::{Decodable, Encodable, ReadExt, SerialDecodable, SerialEncodable};
-
-#[derive(SerialEncodable, SerialDecodable, Clone)]
-pub struct PrivMsgEvent {
-    pub nick: String,
-    pub msg: String,
-    pub target: String,
-}
-
-#[derive(Clone)]
-pub enum EventAction {
-    PrivMsg(PrivMsgEvent),
-}
-
-impl std::string::ToString for PrivMsgEvent {
-    fn to_string(&self) -> String {
-        format!(":{}!anon@dark.fi PRIVMSG {} :{}\r\n", self.nick, self.target, self.msg)
-    }
-}
-
-impl Encodable for EventAction {
-    fn encode<S: io::Write>(&self, mut s: S) -> core::result::Result<usize, io::Error> {
-        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) -> core::result::Result<Self, io::Error> {
-        let type_id = d.read_u8()?;
-        match type_id {
-            0 => Ok(Self::PrivMsg(PrivMsgEvent::decode(d)?)),
-            _ => Err(io::Error::new(io::ErrorKind::Other, "Bad type ID byte for Event")),
-        }
-    }
-}

+ 0 - 388
bin/ircd2/src/protocol_event.rs

@@ -1,388 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::collections::{HashMap, VecDeque};
-
-use async_std::sync::{Arc, Mutex};
-use async_trait::async_trait;
-use darkfi_serial::{SerialDecodable, SerialEncodable};
-use log::debug;
-use rand::{rngs::OsRng, RngCore};
-
-use darkfi::{net, util::async_util::sleep, Result};
-
-use crate::{
-    model::{Event, EventId, ModelPtr},
-    settings::get_current_time,
-};
-
-const UNREAD_EVENT_EXPIRE_TIME: u64 = 3600; // in seconds
-const SIZE_OF_SEEN_BUFFER: usize = 65536;
-const MAX_CONFIRM: u8 = 4;
-
-#[derive(Clone)]
-struct RingBuffer<T> {
-    pub items: VecDeque<T>,
-}
-
-impl<T: Eq + PartialEq + Clone> RingBuffer<T> {
-    pub fn new(capacity: usize) -> Self {
-        let items = VecDeque::with_capacity(capacity);
-        Self { items }
-    }
-
-    pub fn push(&mut self, val: T) {
-        if self.items.len() == self.items.capacity() {
-            self.items.pop_front();
-        }
-        self.items.push_back(val);
-    }
-
-    pub fn contains(&self, val: &T) -> bool {
-        self.items.contains(val)
-    }
-}
-
-type InvId = u64;
-
-#[derive(SerialEncodable, SerialDecodable, Clone, Debug, PartialEq, Eq, Hash)]
-struct InvItem {
-    id: InvId,
-    hash: EventId,
-}
-
-#[derive(SerialDecodable, SerialEncodable, Clone, Debug)]
-struct Inv {
-    invs: Vec<InvItem>,
-}
-
-#[derive(SerialDecodable, SerialEncodable, Clone, Debug)]
-struct SyncEvent {
-    leaves: Vec<EventId>,
-}
-
-#[derive(SerialDecodable, SerialEncodable, Clone, Debug)]
-struct GetData {
-    events: Vec<EventId>,
-}
-
-pub type SeenPtr<T> = Arc<Seen<T>>;
-
-pub struct Seen<T> {
-    seen: Mutex<RingBuffer<T>>,
-}
-
-impl<T: Eq + PartialEq + Clone> Seen<T> {
-    pub fn new() -> SeenPtr<T> {
-        Arc::new(Self { seen: Mutex::new(RingBuffer::new(SIZE_OF_SEEN_BUFFER)) })
-    }
-
-    pub async fn push(&self, item: &T) -> bool {
-        let seen = &mut self.seen.lock().await;
-        if !seen.contains(item) {
-            seen.push(item.clone());
-            return true
-        }
-        false
-    }
-}
-
-pub type UnreadEventsPtr = Arc<Mutex<UnreadEvents>>;
-
-pub struct UnreadEvents {
-    events: HashMap<EventId, Event>,
-}
-
-impl UnreadEvents {
-    pub fn new() -> UnreadEventsPtr {
-        Arc::new(Mutex::new(Self { events: HashMap::new() }))
-    }
-
-    fn contains(&self, key: &EventId) -> bool {
-        self.events.contains_key(key)
-    }
-
-    fn get(&self, key: &EventId) -> Option<Event> {
-        self.events.get(key).cloned()
-    }
-
-    // Increase the read_confirms for an event, if it has exceeded the MAX_CONFIRM
-    // then remove it from the hash_map and return Some(event), otherwise return None
-    fn inc_read_confirms(&mut self, key: &EventId) -> Option<Event> {
-        let mut result = None;
-
-        if let Some(event) = self.events.get_mut(key) {
-            event.read_confirms += 1;
-            if event.read_confirms >= MAX_CONFIRM {
-                result = Some(event.clone())
-            }
-        }
-
-        if result.is_some() {
-            self.events.remove(key);
-        }
-
-        result
-    }
-
-    fn insert(&mut self, event: &Event) {
-        // prune expired events
-        let mut prune_ids = vec![];
-        for (id, e) in self.events.iter() {
-            if e.timestamp + (UNREAD_EVENT_EXPIRE_TIME * 1000) < get_current_time() {
-                prune_ids.push(*id);
-            }
-        }
-        for id in prune_ids {
-            self.events.remove(&id);
-        }
-
-        self.events.insert(event.hash(), event.clone());
-    }
-}
-
-pub struct ProtocolEvent {
-    jobsman: net::ProtocolJobsManagerPtr,
-    event_sub: net::MessageSubscription<Event>,
-    inv_sub: net::MessageSubscription<Inv>,
-    getdata_sub: net::MessageSubscription<GetData>,
-    syncevent_sub: net::MessageSubscription<SyncEvent>,
-    p2p: net::P2pPtr,
-    channel: net::ChannelPtr,
-    model: ModelPtr,
-    seen_event: SeenPtr<EventId>,
-    seen_inv: SeenPtr<InvId>,
-    unread_events: UnreadEventsPtr,
-}
-
-impl ProtocolEvent {
-    pub async fn init(
-        channel: net::ChannelPtr,
-        p2p: net::P2pPtr,
-        model: ModelPtr,
-        seen_event: SeenPtr<EventId>,
-        seen_inv: SeenPtr<InvId>,
-        unread_events: UnreadEventsPtr,
-    ) -> net::ProtocolBasePtr {
-        let message_subsytem = channel.get_message_subsystem();
-        message_subsytem.add_dispatch::<Event>().await;
-        message_subsytem.add_dispatch::<Inv>().await;
-        message_subsytem.add_dispatch::<GetData>().await;
-        message_subsytem.add_dispatch::<SyncEvent>().await;
-
-        let event_sub =
-            channel.clone().subscribe_msg::<Event>().await.expect("Missing Event dispatcher!");
-
-        let inv_sub = channel.subscribe_msg::<Inv>().await.expect("Missing Inv dispatcher!");
-
-        let getdata_sub =
-            channel.clone().subscribe_msg::<GetData>().await.expect("Missing GetData dispatcher!");
-
-        let syncevent_sub = channel
-            .clone()
-            .subscribe_msg::<SyncEvent>()
-            .await
-            .expect("Missing SyncEvent dispatcher!");
-
-        Arc::new(Self {
-            jobsman: net::ProtocolJobsManager::new("ProtocolEvent", channel.clone()),
-            event_sub,
-            inv_sub,
-            getdata_sub,
-            syncevent_sub,
-            p2p,
-            channel,
-            model,
-            seen_event,
-            seen_inv,
-            unread_events,
-        })
-    }
-
-    async fn handle_receive_event(self: Arc<Self>) -> Result<()> {
-        debug!(target: "ircd", "ProtocolEvent::handle_receive_event() [START]");
-        let exclude_list = vec![self.channel.address()];
-        loop {
-            let event = self.event_sub.receive().await?;
-            let mut event = (*event).to_owned();
-
-            if !self.seen_event.push(&event.hash()).await {
-                continue
-            }
-
-            event.read_confirms += 1;
-
-            if event.read_confirms >= MAX_CONFIRM {
-                self.new_event(&event).await?;
-            } else {
-                self.unread_events.lock().await.insert(&event);
-                self.send_inv(&event).await?;
-            }
-
-            // Broadcast the msg
-            self.p2p.broadcast_with_exclude(event, &exclude_list).await?;
-        }
-    }
-
-    async fn handle_receive_inv(self: Arc<Self>) -> Result<()> {
-        debug!(target: "ircd", "ProtocolEvent::handle_receive_inv() [START]");
-        let exclude_list = vec![self.channel.address()];
-        loop {
-            let inv = self.inv_sub.receive().await?;
-            let inv = (*inv).to_owned();
-
-            for inv in inv.invs.iter() {
-                if !self.seen_inv.push(&inv.id).await {
-                    continue
-                }
-
-                {
-                    let mut unread_events = self.unread_events.lock().await;
-                    if !unread_events.contains(&inv.hash) {
-                        self.send_getdata(vec![inv.hash]).await?;
-                    } else if let Some(event) = unread_events.inc_read_confirms(&inv.hash) {
-                        self.new_event(&event).await?;
-                    }
-                }
-            }
-
-            // Broadcast the inv msg
-            self.p2p.broadcast_with_exclude(inv, &exclude_list).await?;
-        }
-    }
-    async fn handle_receive_getdata(self: Arc<Self>) -> Result<()> {
-        debug!(target: "ircd", "ProtocolEvent::handle_receive_getdata() [START]");
-        loop {
-            let getdata = self.getdata_sub.receive().await?;
-            let events = (*getdata).to_owned().events;
-
-            for event_id in events {
-                let unread_event = self.unread_events.lock().await.get(&event_id);
-                if let Some(event) = unread_event {
-                    self.channel.send(event).await?;
-                    continue
-                }
-
-                let model_event = self.model.lock().await.get_event(&event_id);
-                if let Some(event) = model_event {
-                    self.channel.send(event).await?;
-                }
-            }
-        }
-    }
-
-    async fn handle_receive_syncevent(self: Arc<Self>) -> Result<()> {
-        debug!(target: "ircd", "ProtocolEvent::handle_receive_syncevent() [START]");
-        loop {
-            let syncevent = self.syncevent_sub.receive().await?;
-
-            let model = self.model.lock().await;
-            let leaves = model.find_leaves();
-
-            if leaves == syncevent.leaves {
-                continue
-            }
-
-            for leaf in syncevent.leaves.iter() {
-                if leaves.contains(leaf) {
-                    continue
-                }
-
-                let children = model.get_event_children(leaf);
-
-                for child in children {
-                    self.channel.send(child).await?;
-                }
-            }
-        }
-    }
-
-    // every 2 seconds send a SyncEvent msg
-    async fn send_sync_hash_loop(self: Arc<Self>) -> Result<()> {
-        loop {
-            sleep(2).await;
-            let leaves = self.model.lock().await.find_leaves();
-            self.channel.send(SyncEvent { leaves }).await?;
-        }
-    }
-
-    async fn new_event(&self, event: &Event) -> Result<()> {
-        let mut model = self.model.lock().await;
-        if model.is_orphan(event) {
-            self.send_getdata(vec![event.hash()]).await?;
-        } else {
-            model.add(event.clone());
-        }
-
-        Ok(())
-    }
-
-    async fn send_inv(&self, event: &Event) -> Result<()> {
-        let id = OsRng.next_u64();
-        self.p2p.broadcast(Inv { invs: vec![InvItem { id, hash: event.hash() }] }).await?;
-        Ok(())
-    }
-
-    async fn send_getdata(&self, events: Vec<EventId>) -> Result<()> {
-        self.channel.send(GetData { events }).await?;
-        Ok(())
-    }
-}
-
-#[async_trait]
-impl net::ProtocolBase for ProtocolEvent {
-    async fn start(self: Arc<Self>, executor: Arc<smol::Executor<'_>>) -> Result<()> {
-        debug!(target: "ircd", "ProtocolEvent::start() [START]");
-        self.jobsman.clone().start(executor.clone());
-        self.jobsman.clone().spawn(self.clone().handle_receive_event(), executor.clone()).await;
-        self.jobsman.clone().spawn(self.clone().handle_receive_inv(), executor.clone()).await;
-        self.jobsman.clone().spawn(self.clone().handle_receive_getdata(), executor.clone()).await;
-        self.jobsman.clone().spawn(self.clone().handle_receive_syncevent(), executor.clone()).await;
-        self.jobsman.clone().spawn(self.clone().send_sync_hash_loop(), executor.clone()).await;
-        debug!(target: "ircd", "ProtocolEvent::start() [END]");
-        Ok(())
-    }
-
-    fn name(&self) -> &'static str {
-        "ProtocolEvent"
-    }
-}
-
-impl net::Message for Event {
-    fn name() -> &'static str {
-        "event"
-    }
-}
-
-impl net::Message for Inv {
-    fn name() -> &'static str {
-        "inv"
-    }
-}
-
-impl net::Message for SyncEvent {
-    fn name() -> &'static str {
-        "syncevent"
-    }
-}
-
-impl net::Message for GetData {
-    fn name() -> &'static str {
-        "getdata"
-    }
-}

+ 0 - 71
bin/ircd2/src/rpc.rs

@@ -1,71 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use async_trait::async_trait;
-use log::debug;
-use serde_json::{json, Value};
-use url::Url;
-
-use darkfi::{
-    net,
-    rpc::{
-        jsonrpc::{ErrorCode, JsonError, JsonRequest, JsonResponse, JsonResult},
-        server::RequestHandler,
-    },
-};
-
-pub struct JsonRpcInterface {
-    pub addr: Url,
-    pub p2p: net::P2pPtr,
-}
-
-#[async_trait]
-impl RequestHandler for JsonRpcInterface {
-    async fn handle_request(&self, req: JsonRequest) -> JsonResult {
-        if req.params.as_array().is_none() {
-            return JsonError::new(ErrorCode::InvalidRequest, None, req.id).into()
-        }
-
-        debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
-
-        match req.method.as_str() {
-            Some("ping") => self.pong(req.id, req.params).await,
-            Some("get_info") => self.get_info(req.id, req.params).await,
-            Some(_) | None => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
-        }
-    }
-}
-
-impl JsonRpcInterface {
-    // RPCAPI:
-    // Replies to a ping method.
-    // --> {"jsonrpc": "2.0", "method": "ping", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", "result": "pong", "id": 42}
-    async fn pong(&self, id: Value, _params: Value) -> JsonResult {
-        JsonResponse::new(json!("pong"), id).into()
-    }
-
-    // RPCAPI:
-    // Retrieves P2P network information.
-    // --> {"jsonrpc": "2.0", "method": "get_info", "params": [], "id": 42}
-    // <-- {"jsonrpc": "2.0", result": {"nodeID": [], "nodeinfo": [], "id": 42}
-    async fn get_info(&self, id: Value, _params: Value) -> JsonResult {
-        let resp = self.p2p.get_info().await;
-        JsonResponse::new(resp, id).into()
-    }
-}

+ 0 - 205
bin/ircd2/src/settings.rs

@@ -1,205 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use crypto_box::SalsaBox;
-use log::error;
-use serde::{self, Deserialize, Serialize};
-use std::collections::HashMap;
-use structopt::StructOpt;
-use structopt_toml::StructOptToml;
-use url::Url;
-
-use darkfi::{net::settings::SettingsOpt, Result};
-
-// Location for config file
-pub const CONFIG_FILE: &str = "ircd_config.toml";
-pub const CONFIG_FILE_CONTENTS: &str = include_str!("../ircd_config.toml");
-
-// Msg config
-pub const MAXIMUM_LENGTH_OF_MESSAGE: usize = 1024;
-pub const MAXIMUM_LENGTH_OF_NICKNAME: usize = 32;
-
-// IRC Client
-pub enum RPL {
-    NoTopic = 331,
-    Topic = 332,
-    NameReply = 353,
-    EndOfNames = 366,
-}
-
-/// ircd cli
-#[derive(Clone, Deserialize, StructOpt, StructOptToml)]
-#[serde(default)]
-#[structopt(name = "ircd")]
-pub struct Args {
-    /// Sets a custom config file
-    #[structopt(long)]
-    pub config: Option<String>,
-
-    /// JSON-RPC listen URL
-    #[structopt(long = "rpc", default_value = "tcp://127.0.0.1:25550")]
-    pub rpc_listen: Url,
-
-    /// IRC listen URL
-    #[structopt(long = "irc", default_value = "tcp://127.0.0.1:6667")]
-    pub irc_listen: Url,
-
-    /// Optional TLS certificate file path if `irc_listen` uses TLS
-    pub irc_tls_cert: Option<String>,
-
-    /// Optional TLS certificate key file path if `irc_listen` uses TLS
-    pub irc_tls_secret: Option<String>,
-
-    /// Generate a new NaCl keypair and exit
-    #[structopt(long)]
-    pub gen_keypair: bool,
-
-    /// Path to save keypair in
-    #[structopt(short)]
-    pub output: Option<String>,
-
-    /// Autojoin channels
-    #[structopt(long)]
-    pub autojoin: Vec<String>,
-
-    /// Password
-    #[structopt(long)]
-    pub password: Option<String>,
-
-    /// Channels
-    #[structopt(skip)]
-    pub channels: HashMap<String, ChannelInfo>,
-
-    /// Channels
-    #[structopt(skip)]
-    pub contacts: HashMap<String, ContactInfo>,
-
-    /// Private key
-    #[structopt(skip)]
-    pub private_key: Option<String>,
-
-    #[structopt(flatten)]
-    pub net: SettingsOpt,
-
-    /// Increase verbosity
-    #[structopt(short, parse(from_occurrences))]
-    pub verbose: u8,
-}
-
-/// This struct holds information about preconfigured contacts.
-/// In the TOML configuration file, we can configure contacts as such:
-///
-/// ```toml
-/// [contact."nick"]
-/// pubkey = "7CkVuFgwTUpJn5Sv67Q3fyEDpa28yrSeL5Hg2GqQ4jfM"
-/// ```
-#[derive(Default, Clone, Debug, Deserialize, Serialize)]
-pub struct ContactInfo {
-    pub pubkey: Option<String>,
-}
-
-impl ContactInfo {
-    pub fn new() -> Self {
-        Self { pubkey: None }
-    }
-
-    pub fn salt_box(&self, private_key: &str, contact_name: &str) -> Option<SalsaBox> {
-        if let Ok(private) = parse_priv(private_key) {
-            if let Some(p) = &self.pubkey {
-                if let Ok(public) = parse_pub(p) {
-                    return Some(SalsaBox::new(&public, &private))
-                } else {
-                    error!("Uncorrect public key in for contact {}", contact_name);
-                }
-            }
-        } else {
-            error!("Uncorrect Private key in config",);
-        }
-
-        None
-    }
-}
-
-/// This struct holds information about preconfigured channels.
-/// In the TOML configuration file, we can configure channels as such:
-/// ```toml
-/// [channel."#dev"]
-/// secret = "GvH4kno3kUu6dqPrZ8zjMhqxTUDZ2ev16EdprZiZJgj1"
-/// topic = "DarkFi Development Channel"
-/// ```
-/// Having a secret will enable a NaCl box that is able to encrypt and
-/// decrypt messages in this channel using this set shared secret.
-/// The secret should be shared OOB, via a secure channel.
-/// Having a topic set is useful if one wants to have a topic in the
-/// configured channel. It is not shared with others, but it is useful
-/// for personal reference.
-#[derive(Default, Clone, Debug, Serialize, Deserialize)]
-pub struct ChannelInfo {
-    /// Optional topic for the channel
-    pub topic: Option<String>,
-    /// Optional NaCl box for the channel, used for {en,de}cryption.
-    pub secret: Option<String>,
-    /// Flag indicates whether the user has joined the channel or not
-    #[serde(default, skip_serializing)]
-    pub joined: bool,
-    /// All nicknames which are visible on the channel
-    #[serde(default, skip_serializing)]
-    pub names: Vec<String>,
-}
-
-impl ChannelInfo {
-    pub fn new() -> Self {
-        Self { topic: None, secret: None, joined: false, names: vec![] }
-    }
-
-    pub fn salt_box(&self, channel_name: &str) -> Option<SalsaBox> {
-        if let Some(s) = &self.secret {
-            let secret = parse_priv(s);
-
-            if secret.is_err() {
-                error!("Uncorrect secret key for the channel {}", channel_name);
-                return None
-            }
-
-            let secret = secret.unwrap();
-            let public = secret.public_key();
-            return Some(SalsaBox::new(&public, &secret))
-        }
-        None
-    }
-}
-
-pub 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 parse_priv(key: &str) -> Result<crypto_box::SecretKey> {
-    let bytes: [u8; 32] = bs58::decode(key).into_vec()?.try_into().unwrap();
-    Ok(crypto_box::SecretKey::from(bytes))
-}
-
-fn parse_pub(key: &str) -> Result<crypto_box::PublicKey> {
-    let bytes: [u8; 32] = bs58::decode(key).into_vec()?.try_into().unwrap();
-    Ok(crypto_box::PublicKey::from(bytes))
-}

+ 0 - 45
bin/ircd2/src/view.rs

@@ -1,45 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::collections::HashMap;
-
-use darkfi::Result;
-
-use crate::{
-    events_queue::EventsQueuePtr,
-    model::{Event, EventId},
-};
-
-pub struct View {
-    seen: HashMap<EventId, Event>,
-    events_queue: EventsQueuePtr,
-}
-
-impl View {
-    pub fn new(events_queue: EventsQueuePtr) -> Self {
-        Self { seen: HashMap::new(), events_queue }
-    }
-
-    pub async fn process(&mut self) -> Result<()> {
-        loop {
-            let new_event = self.events_queue.fetch().await?;
-            // TODO sort the events
-            self.seen.insert(new_event.hash(), new_event);
-        }
-    }
-}