Explorar el Código

darkirc/nickserv: Feed RLN identity through REGISTER

parazyd hace 2 años
padre
commit
1e5e56c9ea

+ 3 - 0
bin/darkirc/src/irc/services/mod.rs

@@ -16,5 +16,8 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+/// Rate-Limit Nullifiers
+pub mod rln;
+
 /// NickServ implementation, used for account management
 pub mod nickserv;

+ 78 - 14
bin/darkirc/src/irc/services/nickserv.rs

@@ -16,19 +16,24 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::{str::SplitAsciiWhitespace, sync::Arc};
+use std::{
+    str::{FromStr, SplitAsciiWhitespace},
+    sync::Arc,
+};
 
 use darkfi::Result;
 use darkfi_sdk::crypto::SecretKey;
 use darkfi_serial::serialize_async;
-use rand::rngs::OsRng;
 use smol::lock::RwLock;
 
-use super::super::{client::ReplyType, rpl::*};
+use super::{
+    super::{client::ReplyType, rpl::*},
+    rln::RlnIdentity,
+};
 use crate::IrcServer;
 
 const ACCOUNTS_DB_PREFIX: &str = "darkirc_account_";
-const ACCOUNTS_KEY_SECRET: &[u8] = b"secret_key";
+const ACCOUNTS_KEY_RLN_IDENTITY: &[u8] = b"rln_identity";
 
 const NICKSERV_USAGE: &str = r#"***** NickServ Help ***** 
 
@@ -106,14 +111,37 @@ impl NickServ {
         nick: &str,
         tokens: &mut SplitAsciiWhitespace<'_>,
     ) -> Result<Vec<ReplyType>> {
-        let Some(account_name) = tokens.next() else {
-            return Ok(vec![ReplyType::Notice((
-                "NickServ".to_string(),
-                nick.to_string(),
-                "Invalid syntax. Use `REGISTER <account_name>`.".to_string(),
-            ))])
+        // Gather the tokens
+        let account_name = tokens.next();
+        let identity_nullifier = tokens.next();
+        let identity_trapdoor = tokens.next();
+        let leaf_pos = tokens.next();
+
+        if account_name.is_none() ||
+            identity_nullifier.is_none() ||
+            identity_trapdoor.is_none() ||
+            leaf_pos.is_none()
+        {
+            return Ok(vec![
+                ReplyType::Notice((
+                    "NickServ".to_string(),
+                    nick.to_string(),
+                    "Invalid syntax.".to_string(),
+                )),
+                ReplyType::Notice((
+                    "NickServ".to_string(),
+                    nick.to_string(),
+                    "Use `REGISTER <account_name> <identity_nullifier> <identity_trapdoor> <leaf_pos>`."
+                        .to_string(),
+                )),
+            ])
         };
 
+        let account_name = account_name.unwrap();
+        let identity_nullifier = identity_nullifier.unwrap();
+        let identity_trapdoor = identity_trapdoor.unwrap();
+        let leaf_pos = leaf_pos.unwrap();
+
         // Open the sled tree
         let db = self
             .server
@@ -125,13 +153,49 @@ impl NickServ {
             return Ok(vec![ReplyType::Notice((
                 "NickServ".to_string(),
                 nick.to_string(),
-                "This account is already registered.".to_string(),
+                "This account name is already registered.".to_string(),
             ))])
         }
 
-        // Create a new secret key and insert it into the db.
-        let secret = SecretKey::random(&mut OsRng);
-        db.insert(ACCOUNTS_KEY_SECRET, serialize_async(&secret).await)?;
+        // TODO: WIF
+        // Parse the secrets
+        let identity_nullifier = match SecretKey::from_str(identity_nullifier) {
+            Ok(v) => v,
+            Err(e) => {
+                return Ok(vec![ReplyType::Notice((
+                    "NickServ".to_string(),
+                    nick.to_string(),
+                    format!("Invalid identity_nullifier: {}", e),
+                ))])
+            }
+        };
+
+        let identity_trapdoor = match SecretKey::from_str(identity_trapdoor) {
+            Ok(v) => v,
+            Err(e) => {
+                return Ok(vec![ReplyType::Notice((
+                    "NickServ".to_string(),
+                    nick.to_string(),
+                    format!("Invalid identity_trapdoor: {}", e),
+                ))])
+            }
+        };
+
+        let leaf_pos = match u64::from_str(leaf_pos) {
+            Ok(v) => v,
+            Err(e) => {
+                return Ok(vec![ReplyType::Notice((
+                    "NickServ".to_string(),
+                    nick.to_string(),
+                    format!("Invalid leaf_pos: {}", e),
+                ))])
+            }
+        };
+
+        // Create a new RLN identity and insert it into the db tree
+        let rln_identity =
+            RlnIdentity { identity_nullifier, identity_trapdoor, leaf_pos: leaf_pos.into() };
+        db.insert(ACCOUNTS_KEY_RLN_IDENTITY, serialize_async(&rln_identity).await)?;
 
         Ok(vec![ReplyType::Notice((
             "NickServ".to_string(),

+ 31 - 0
bin/darkirc/src/irc/services/rln.rs

@@ -0,0 +1,31 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2024 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 darkfi_sdk::{bridgetree, crypto::SecretKey};
+use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
+
+/// Rate-Limit Nullifier account data
+#[derive(Debug, Copy, Clone, SerialEncodable, SerialDecodable)]
+pub struct RlnIdentity {
+    /// Identity nullifier secret
+    pub identity_nullifier: SecretKey,
+    /// Identity trapdoor secret
+    pub identity_trapdoor: SecretKey,
+    /// Leaf position of the identity commitment in the accounts' Merkle tree
+    pub leaf_pos: bridgetree::Position,
+}