Explorar o código

event_graph: added account registeration zk circuit, removed old privmsg struct, plust few small fixes

dasman hai 7 meses
pai
achega
e9141d5831

+ 1 - 2
Makefile

@@ -15,8 +15,7 @@ RUST_TARGET = $(shell rustc -Vv | grep '^host: ' | cut -d' ' -f2)
 
 # List of zkas circuits to compile, used for tests
 PROOFS_SRC = \
-	$(shell find proof -type f -name '*.zk') \
-	$(shell find bin/darkirc/proof -type f -name '*.zk')
+	$(shell find proof -type f -name '*.zk')
 
 PROOFS_BIN = $(PROOFS_SRC:=.bin)
 

+ 40 - 7
bin/darkirc/src/crypto/rln.rs

@@ -43,13 +43,15 @@ pub const RLN_GENESIS: u64 = 1_738_688_400_000;
 /// RLN epoch length in millis
 pub const RLN_EPOCH_LEN: u64 = 600_000; // 10 min
 
+pub const RLN2_REGISTER_ZKBIN: &[u8] =
+    include_bytes!("../../../../src/event_graph/proof/rlnv2-diff-register.zk.bin");
 pub const RLN2_SIGNAL_ZKBIN: &[u8] =
-    include_bytes!("../../../../src/event_graph/proofs/rlnv2-diff-signal.zk.bin");
+    include_bytes!("../../../../src/event_graph/proof/rlnv2-diff-signal.zk.bin");
 pub const RLN2_SLASH_ZKBIN: &[u8] =
-    include_bytes!("../../../../src/event_graph/proofs/rlnv2-diff-slash.zk.bin");
+    include_bytes!("../../../../src/event_graph/proof/rlnv2-diff-slash.zk.bin");
 
 /// TODO: this should be configurable
-pub const USER_MSG_LIMIT: u64 = 6;
+pub const MAX_MSG_LIMIT: u64 = 20;
 
 /// Find closest epoch to given timestamp
 pub fn closest_epoch(timestamp: u64) -> u64 {
@@ -85,8 +87,8 @@ impl RlnIdentity {
                 pallas::Base::random(&mut rng),
             ]),
             trapdoor: poseidon_hash([RLN_TRAPDOOR_DERIVATION_PATH, pallas::Base::random(&mut rng)]),
-            user_message_limit: USER_MSG_LIMIT,
-            message_id: 1,
+            user_message_limit: MAX_MSG_LIMIT,
+            message_id: 0,
             last_epoch: closest_epoch(UNIX_EPOCH.elapsed().unwrap().as_millis() as u64),
         }
     }
@@ -98,6 +100,36 @@ impl RlnIdentity {
         poseidon_hash([identity_secret_hash])
     }
 
+    pub fn create_register_proof(
+        &self,
+        event: &Event,
+        identities_tree: &mut SmtMemoryFp,
+        register_pk: &ProvingKey,
+    ) -> Result<Proof> {
+        let witnesses = vec![
+            Witness::Base(Value::known(self.nullifier)),
+            Witness::Base(Value::known(self.trapdoor)),
+            Witness::Base(Value::known(pallas::Base::from(self.user_message_limit))),
+            Witness::Base(Value::known(pallas::Base::from(MAX_MSG_LIMIT))),
+        ];
+
+        let commitment = self.commitment();
+        let public_inputs = vec![commitment, pallas::Base::from(self.user_message_limit)];
+
+        info!(target: "crypto::rln::create_register_proof", "[RLN] Creating register proof for account {}", event.header.id());
+        let register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN)?;
+        let register_circuit = ZkCircuit::new(witnesses, &register_zkbin);
+
+        let proof =
+            Proof::create(&register_pk, &[register_circuit], &public_inputs, &mut OsRng).unwrap();
+
+        let leaf = vec![commitment];
+        let leaf: Vec<_> = leaf.into_iter().map(|l| (l, l)).collect();
+        // TODO: Recipients should verify that identity doesn't exist already before insert.
+        identities_tree.insert_batch(leaf.clone()).unwrap(); // leaf == pos
+        Ok(proof)
+    }
+
     pub fn create_signal_proof(
         &self,
         event: &Event,
@@ -117,10 +149,11 @@ impl RlnIdentity {
         let internal_nullifier = poseidon_hash([a_1]);
 
         // 2. Inclusion proof
+        let commitment = self.commitment();
         let identity_root = identity_tree.root();
-        let identity_path = identity_tree.prove_membership(&self.commitment());
+        let identity_path = identity_tree.prove_membership(&commitment);
         // TODO: Delete me later
-        assert!(identity_path.verify(&identity_root, &self.commitment(), &self.commitment()));
+        assert!(identity_path.verify(&identity_root, &commitment, &commitment));
 
         // 3. Create ZK proof
         let witnesses = vec![

+ 17 - 12
bin/darkirc/src/irc/client.rs

@@ -47,7 +47,7 @@ use tracing::{debug, error, info, warn};
 
 use super::{
     server::{IrcServer, MAX_MSG_LEN},
-    Msg, NickServ, OldPrivmsg, SERVER_NAME,
+    NickServ, Privmsg, SERVER_NAME,
 };
 use crate::crypto::rln::{closest_epoch, RlnIdentity, RLN2_SIGNAL_ZKBIN};
 
@@ -214,7 +214,7 @@ impl Client {
 
                                     // If we have a RLN identity, now we'll build a ZK proof.
                                     // Also I really want GOTO in Rust... Fags.
-                                    if let Some(mut rln_identity) = *self.server.rln_identity.write().await {
+                                    if let Some(ref mut rln_identity) = *self.server.rln_identity.write().await {
                                         // If the current epoch is different, we can reset the message counter
                                         if rln_identity.last_epoch != closest_epoch(event.header.timestamp) {
                                             rln_identity.last_epoch = closest_epoch(event.header.timestamp);
@@ -266,7 +266,6 @@ impl Client {
                 // <file:./command.rs::async fn get_history(&self, channels: &HashSet<String>) -> Result<Vec<ReplyType>> {>
                 // for which the logic for delivery should be kept in sync
                 r = self.incoming.receive().fuse() => {
-                    info!("incoming: {:?}", r);
                     // We will skip this if it's our own message.
                     let event_id = r.header.id();
                     if *self.last_sent.read().await == event_id {
@@ -284,11 +283,10 @@ impl Client {
                     }
 
                     // Try to deserialize the `Event`'s content into a `Privmsg`
-                    let mut privmsg = match Msg::deserialize(r.content()).await {
-                        Ok(Msg::V1(old_msg)) => old_msg.into_new(),
-                        Ok(Msg::V2(new_msg)) => new_msg,
+                    let mut privmsg = match deserialize_async_partial(r.content()).await {
+                        Ok((v, _)) => v,
                         Err(e) => {
-                            error!("[IRC CLIENT] Failed deserializing incoming Privmsg event: {e}");
+                            error!(target: "irc::client", "[IRC CLIENT] Failed deserializing event: {e}");
                             continue
                         }
                     };
@@ -370,7 +368,7 @@ impl Client {
                     {
                         Ok((v, _)) => v,
                         Err(e) => {
-                            error!(target: "irc::server", "[RLN] Failed deserializing incoming RLN Identity events: {}", e);
+                            error!(target: "irc::client", "[RLN] Failed deserializing incoming RLN Identity events: {}", e);
                             continue
                         }
                     };
@@ -542,11 +540,18 @@ impl Client {
 
         // Truncate messages longer than MAX_MSG_LEN
         let msg = if msg.len() > MAX_MSG_LEN { msg.split_at(MAX_MSG_LEN).0 } else { msg };
-        OldPrivmsg { channel, nick, msg: msg.to_string() }
-    }
 
-    // Internal helper function that creates an Event from PRIVMSG arguments
-    async fn privmsg_to_event(&self, mut privmsg: OldPrivmsg) -> Event {
+        // TODO: This is kept as old version of privmsg, since now we
+        // can deserialize both old and new versions, after some time
+        // this will be replaced with Privmsg (new version)
+        let mut privmsg = Privmsg {
+            version: 0,
+            channel,
+            nick: self.nickname.read().await.to_string(),
+            msg: msg.to_string(),
+            msg_type: 0,
+        };
+
         // Encrypt the Privmsg if an encryption method is available.
         self.server.try_encrypt(&mut privmsg).await;
 

+ 4 - 4
bin/darkirc/src/irc/command.rs

@@ -52,13 +52,14 @@
 use std::{collections::HashSet, sync::atomic::Ordering::SeqCst};
 
 use darkfi::Result;
+use darkfi_serial::deserialize_async_partial;
 use tracing::{error, info};
 
 use super::{
     client::{Client, ReplyType},
     rpl::*,
     server::MAX_NICK_LEN,
-    IrcChannel, Msg, SERVER_NAME,
+    IrcChannel, SERVER_NAME,
 };
 use crate::crypto::bcrypt::bcrypt_hash_password;
 
@@ -931,9 +932,8 @@ impl Client {
             }
 
             // Try to deserialize it. (Here we skip errors)
-            let mut privmsg = match Msg::deserialize(event.content()).await {
-                Ok(Msg::V1(old_msg)) => old_msg.into_new(),
-                Ok(Msg::V2(new_msg)) => new_msg,
+            let mut privmsg = match deserialize_async_partial(event.content()).await {
+                Ok((v, _)) => v,
                 Err(_) => continue,
             };
 

+ 1 - 76
bin/darkirc/src/irc/mod.rs

@@ -19,8 +19,7 @@
 use std::{collections::HashSet, sync::Arc};
 
 use crypto_box::ChaChaBox;
-use darkfi::{Error, Result};
-use darkfi_serial::{async_trait, deserialize_async_partial, SerialDecodable, SerialEncodable};
+use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
 
 /// IRC client state
 pub(crate) mod client;
@@ -41,32 +40,6 @@ pub(crate) mod rpl;
 /// Hardcoded server name
 const SERVER_NAME: &str = "irc.dark.fi";
 
-pub trait Priv {
-    fn channel(&mut self) -> &mut String;
-    fn nick(&mut self) -> &mut String;
-    fn msg(&mut self) -> &mut String;
-}
-
-/// IRC PRIVMSG (old version)
-#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
-pub struct OldPrivmsg {
-    pub channel: String,
-    pub nick: String,
-    pub msg: String,
-}
-
-impl OldPrivmsg {
-    pub fn into_new(self) -> Privmsg {
-        Privmsg {
-            version: 0,
-            msg_type: 0,
-            channel: self.channel.clone(),
-            nick: self.nick.clone(),
-            msg: self.msg.clone(),
-        }
-    }
-}
-
 /// IRC PRIVMSG (new version)
 #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
 pub struct Privmsg {
@@ -77,54 +50,6 @@ pub struct Privmsg {
     pub msg: String,
 }
 
-impl Priv for OldPrivmsg {
-    fn channel(&mut self) -> &mut String {
-        &mut self.channel
-    }
-
-    fn nick(&mut self) -> &mut String {
-        &mut self.nick
-    }
-
-    fn msg(&mut self) -> &mut String {
-        &mut self.msg
-    }
-}
-impl Priv for Privmsg {
-    fn channel(&mut self) -> &mut String {
-        &mut self.channel
-    }
-
-    fn nick(&mut self) -> &mut String {
-        &mut self.nick
-    }
-
-    fn msg(&mut self) -> &mut String {
-        &mut self.msg
-    }
-}
-
-pub enum Msg {
-    V1(OldPrivmsg),
-    V2(Privmsg),
-}
-
-impl Msg {
-    pub async fn deserialize(bytes: &[u8]) -> Result<Self> {
-        let old_privmsg = deserialize_async_partial(bytes).await;
-        if let Ok((old_msg, _)) = old_privmsg {
-            return Ok(Msg::V1(old_msg))
-        }
-
-        let new_privmsg = deserialize_async_partial(bytes).await;
-        if let Ok((new_msg, _)) = new_privmsg {
-            return Ok(Msg::V2(new_msg))
-        }
-
-        Err(Error::Custom("Unknown message format".into()))
-    }
-}
-
 /// IRC channel definition
 #[derive(Clone)]
 pub struct IrcChannel {

+ 54 - 29
bin/darkirc/src/irc/server.rs

@@ -22,7 +22,7 @@ use darkfi::{
     event_graph::Event,
     system::{StoppableTask, StoppableTaskPtr, Subscription},
     util::path::expand_path,
-    zk::{empty_witnesses, ProvingKey, VerifyingKey, ZkCircuit},
+    zk::{empty_witnesses, ProvingKey, ZkCircuit},
     zkas::ZkBinary,
     Error, Result,
 };
@@ -49,11 +49,11 @@ use url::Url;
 use super::{
     client::Client,
     services::nickserv::{ACCOUNTS_DB_PREFIX, ACCOUNTS_KEY_RLN_IDENTITY},
-    IrcChannel, IrcContact, Priv, Privmsg,
+    IrcChannel, IrcContact, Privmsg,
 };
 use crate::{
     crypto::{
-        rln::{RlnIdentity, RLN2_SIGNAL_ZKBIN, RLN2_SLASH_ZKBIN},
+        rln::{RlnIdentity, RLN2_REGISTER_ZKBIN, RLN2_SIGNAL_ZKBIN, RLN2_SLASH_ZKBIN},
         saltbox,
     },
     settings::{
@@ -156,7 +156,28 @@ impl IrcServer {
         let mut identity_tree = SmtMemoryFp::new(store, hasher.clone(), &EMPTY_NODES_FP);
 
         // Generate RLN proving and verifying keys, if needed
-        let rln_signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN, false)?;
+        let rln_register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN)?;
+        let rln_register_circuit =
+            ZkCircuit::new(empty_witnesses(&rln_register_zkbin)?, &rln_register_zkbin);
+
+        if server_store.get("rlnv2-diff-register-pk")?.is_none() {
+            info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Register ProvingKey");
+            let provingkey = ProvingKey::build(rln_register_zkbin.k, &rln_register_circuit);
+            let mut buf = vec![];
+            provingkey.write(&mut buf)?;
+            server_store.insert("rlnv2-diff-register-pk", buf)?;
+        }
+
+        // if server_store.get("rlnv2-diff-register-vk")?.is_none() {
+        //     info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Register VerifyingKey");
+        //     let verifyingkey = VerifyingKey::build(rln_register_zkbin.k, &rln_register_circuit);
+        //     let mut buf = vec![];
+        //     verifyingkey.write(&mut buf)?;
+        //     server_store.insert("rlnv2-diff-register-vk", buf)?;
+        // }
+
+        // Generate RLN proving and verifying keys, if needed
+        let rln_signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN)?;
         let rln_signal_circuit =
             ZkCircuit::new(empty_witnesses(&rln_signal_zkbin)?, &rln_signal_zkbin);
 
@@ -168,33 +189,37 @@ impl IrcServer {
             server_store.insert("rlnv2-diff-signal-pk", buf)?;
         }
 
-        if server_store.get("rlnv2-diff-signal-vk")?.is_none() {
-            info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Signal VerifyingKey");
-            let verifyingkey = VerifyingKey::build(rln_signal_zkbin.k, &rln_signal_circuit);
-            let mut buf = vec![];
-            verifyingkey.write(&mut buf)?;
-            server_store.insert("rlnv2-diff-signal-vk", buf)?;
-        }
+        // if server_store.get("rlnv2-diff-signal-vk")?.is_none() {
+        //     info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Signal VerifyingKey");
+        //     let verifyingkey = VerifyingKey::build(rln_signal_zkbin.k, &rln_signal_circuit);
+        //     let mut buf = vec![];
+        //     verifyingkey.write(&mut buf)?;
+        //     server_store.insert("rlnv2-diff-signal-vk", buf)?;
+        // }
+
+        // Generate RLN proving and verifying keys, if needed
+        let rln_slash_zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN)?;
+        let rln_slash_circuit =
+            ZkCircuit::new(empty_witnesses(&rln_slash_zkbin)?, &rln_slash_zkbin);
 
         if server_store.get("rlnv2-diff-slash-pk")?.is_none() {
             info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash ProvingKey");
             let zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false)?;
             let circuit = ZkCircuit::new(empty_witnesses(&zkbin).unwrap(), &zkbin);
             let provingkey = ProvingKey::build(zkbin.k, &circuit);
+            let provingkey = ProvingKey::build(rln_slash_zkbin.k, &rln_slash_circuit);
             let mut buf = vec![];
             provingkey.write(&mut buf)?;
             server_store.insert("rlnv2-diff-slash-pk", buf)?;
         }
 
-        if server_store.get("rlnv2-diff-slash-vk")?.is_none() {
-            info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash VerifyingKey");
-            let zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false)?;
-            let circuit = ZkCircuit::new(empty_witnesses(&zkbin).unwrap(), &zkbin);
-            let verifyingkey = VerifyingKey::build(zkbin.k, &circuit);
-            let mut buf = vec![];
-            verifyingkey.write(&mut buf)?;
-            server_store.insert("rlnv2-diff-slash-vk", buf)?;
-        }
+        // if server_store.get("rlnv2-diff-slash-vk")?.is_none() {
+        //     info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash VerifyingKey");
+        //     let verifyingkey = VerifyingKey::build(rln_slash_zkbin.k, &rln_slash_circuit);
+        //     let mut buf = vec![];
+        //     verifyingkey.write(&mut buf)?;
+        //     server_store.insert("rlnv2-diff-slash-vk", buf)?;
+        // }
 
         // Construct SMT from static DAG
         let mut events = darkirc.event_graph.static_fetch_all().await?;
@@ -403,28 +428,28 @@ impl IrcServer {
     }
 
     /// Try encrypting a given `Privmsg` if there is such a channel/contact.
-    pub async fn try_encrypt<T: Priv>(&self, privmsg: &mut T) {
-        if let Some((name, channel)) = self.channels.read().await.get_key_value(privmsg.channel()) {
+    pub async fn try_encrypt(&self, privmsg: &mut Privmsg) {
+        if let Some((name, channel)) = self.channels.read().await.get_key_value(&privmsg.channel) {
             if let Some(saltbox) = &channel.saltbox {
                 // We will use a dummy channel value of MAX_NICK_LEN,
                 // since its not used, so all encrypted messages look the same.
-                *privmsg.channel() = saltbox::encrypt(saltbox, &[0x00; MAX_NICK_LEN]);
+                privmsg.channel = saltbox::encrypt(saltbox, &[0x00; MAX_NICK_LEN]);
                 // We will pad the name to MAX_NICK_LEN so they all look the same
-                *privmsg.nick() = saltbox::encrypt(saltbox, &Self::pad(privmsg.nick()));
-                *privmsg.msg() = saltbox::encrypt(saltbox, privmsg.msg().as_bytes());
+                privmsg.nick = saltbox::encrypt(saltbox, &Self::pad(&privmsg.nick));
+                privmsg.msg = saltbox::encrypt(saltbox, privmsg.msg.as_bytes());
                 debug!("Successfully encrypted message for {name}");
                 return
             }
         };
 
-        if let Some((name, contact)) = self.contacts.read().await.get_key_value(privmsg.channel()) {
+        if let Some((name, contact)) = self.contacts.read().await.get_key_value(&privmsg.channel) {
             // We will use dummy channel and nick values of MAX_NICK_LEN,
             // since they are not used, so all encrypted messages look the same.
-            *privmsg.channel() = saltbox::encrypt(&contact.saltbox, &[0x00; MAX_NICK_LEN]);
+            privmsg.channel = saltbox::encrypt(&contact.saltbox, &[0x00; MAX_NICK_LEN]);
             // We will encrypt the dummy nick value using our own self saltbox,
             // so we can identify our messages.
-            *privmsg.nick() = saltbox::encrypt(&contact.self_saltbox, &[0x00; MAX_NICK_LEN]);
-            *privmsg.msg() = saltbox::encrypt(&contact.saltbox, privmsg.msg().as_bytes());
+            privmsg.nick = saltbox::encrypt(&contact.self_saltbox, &[0x00; MAX_NICK_LEN]);
+            privmsg.msg = saltbox::encrypt(&contact.saltbox, privmsg.msg.as_bytes());
             debug!("Successfully encrypted message for {name}");
         };
     }

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

@@ -16,16 +16,21 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::{str::SplitAsciiWhitespace, sync::Arc, time::UNIX_EPOCH};
+use std::{io::Cursor, str::SplitAsciiWhitespace, sync::Arc, time::UNIX_EPOCH};
 
-use darkfi::{event_graph::Event, Result};
+use darkfi::{
+    event_graph::Event,
+    zk::{empty_witnesses, ProvingKey, ZkCircuit},
+    zkas::ZkBinary,
+    Error, Result,
+};
 use darkfi_sdk::{crypto::pasta_prelude::PrimeField, pasta::pallas};
 use darkfi_serial::serialize_async;
 use smol::lock::RwLock;
 
 use super::super::{client::ReplyType, rpl::*};
 use crate::{
-    crypto::rln::{closest_epoch, RlnIdentity, USER_MSG_LIMIT},
+    crypto::rln::{closest_epoch, RlnIdentity, RLN2_REGISTER_ZKBIN},
     IrcServer,
 };
 
@@ -139,7 +144,8 @@ impl NickServ {
         let account_name = account_name.unwrap();
         let identity_nullifier = identity_nullifier.unwrap();
         let identity_trapdoor = identity_trapdoor.unwrap();
-        let _user_msg_limit = user_msg_limit.unwrap();
+        let user_msg_limit: u64 =
+            user_msg_limit.unwrap().parse().expect("msg limit must be a number");
 
         // Open the sled tree
         let db =
@@ -188,9 +194,9 @@ impl NickServ {
         let new_rln_identity = RlnIdentity {
             nullifier: identity_nullifier,
             trapdoor: identity_trapdoor,
-            user_message_limit: USER_MSG_LIMIT,
-            message_id: 1, // TODO
-            last_epoch: closest_epoch(UNIX_EPOCH.elapsed().unwrap().as_secs()),
+            user_message_limit: user_msg_limit,
+            message_id: 0, // TODO
+            last_epoch: closest_epoch(UNIX_EPOCH.elapsed().unwrap().as_millis() as u64),
         };
 
         // Store account
@@ -204,17 +210,30 @@ impl NickServ {
         *self.server.rln_identity.write().await = Some(new_rln_identity);
 
         // Update SMT, DAG and broadcast
-        let mut identities_tree = self.server.rln_identity_tree.write().await;
         let rln_commitment = new_rln_identity.commitment();
-
-        let commitment = vec![rln_commitment];
-        let commitment: Vec<_> = commitment.into_iter().map(|l| (l, l)).collect();
-        identities_tree.insert_batch(commitment)?;
-
         let evgr = &self.server.darkirc.event_graph;
         let event = Event::new_static(serialize_async(&rln_commitment).await, evgr).await;
+
+        let mut identity_tree = self.server.rln_identity_tree.write().await;
+
+        // Retrieve the register ZK proving key from the db
+        let register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN)?;
+        let register_circuit = ZkCircuit::new(empty_witnesses(&register_zkbin)?, &register_zkbin);
+        let Some(proving_key) = self.server.server_store.get("rlnv2-diff-register-pk")? else {
+            return Err(Error::DatabaseError(
+                "RLN register proving key not found in server store".to_string(),
+            ))
+        };
+        let mut reader = Cursor::new(proving_key);
+        let proving_key = ProvingKey::read(&mut reader, register_circuit)?;
+
+        let proof =
+            new_rln_identity.create_register_proof(&event, &mut identity_tree, &proving_key)?;
+
+        let blob = serialize_async(&(proof, user_msg_limit)).await;
+
         evgr.static_insert(&event).await?;
-        evgr.static_broadcast(event).await?;
+        evgr.static_broadcast(event, blob).await?;
 
         Ok(vec![ReplyType::Notice((
             "NickServ".to_string(),

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

@@ -238,7 +238,7 @@ pub fn parse_rln_identity(data: &toml::Value) -> Result<Option<RlnIdentity>> {
         user_message_limit,
         // TODO: FIXME: We should probably keep track of these rather than
         // resetting here
-        message_id: 1,
+        message_id: 0,
         last_epoch: closest_epoch(UNIX_EPOCH.elapsed().unwrap().as_secs()),
     }))
 }

+ 53 - 4
src/event_graph/mod.rs

@@ -101,6 +101,10 @@ pub const NULL_PARENTS: [Hash; N_EVENT_PARENTS] = [NULL_ID; N_EVENT_PARENTS];
 /// Maximum number of DAGs to store, this should be configurable
 pub const DAGS_MAX_NUMBER: i8 = 24;
 
+pub const RLN2_REGISTER_ZKBIN: &[u8] = include_bytes!("proof/rlnv2-diff-register.zk.bin");
+pub const RLN2_SIGNAL_ZKBIN: &[u8] = include_bytes!("proof/rlnv2-diff-signal.zk.bin");
+pub const RLN2_SLASH_ZKBIN: &[u8] = include_bytes!("proof/rlnv2-diff-slash.zk.bin");
+
 /// Atomic pointer to an [`EventGraph`] instance.
 pub type EventGraphPtr = Arc<EventGraph>;
 pub type LayerUTips = BTreeMap<u64, HashSet<blake3::Hash>>;
@@ -369,8 +373,12 @@ pub struct EventGraph {
     deg_publisher: PublisherPtr<DegEvent>,
     /// Run in fast mode where if set we sync only headers.
     fast_mode: bool,
+    /// Registering verify key
+    register_vk: VerifyingKey,
     /// Signaling verify key
     signal_vk: VerifyingKey,
+    /// Slashing verify key
+    slash_vk: VerifyingKey,
 }
 
 impl EventGraph {
@@ -396,8 +404,27 @@ impl EventGraph {
         ex: Arc<Executor<'_>>,
     ) -> Result<EventGraphPtr> {
         // Read or build signal verifying key
-        let signal_zkbin = include_bytes!("proofs/rlnv2-diff-signal.zk.bin");
-        let signal_zkbin = ZkBinary::decode(signal_zkbin, false).unwrap();
+        let register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN, false).unwrap();
+        let register_empty_circuit =
+            ZkCircuit::new(empty_witnesses(&register_zkbin).unwrap(), &register_zkbin);
+
+        let register_vk = match sled_db.get("rlnv2-diff-register-vk")? {
+            Some(vk) => {
+                let mut reader = Cursor::new(vk);
+                VerifyingKey::read(&mut reader, register_empty_circuit)?
+            }
+            None => {
+                info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Register VerifyingKey");
+                let verifyingkey = VerifyingKey::build(register_zkbin.k, &register_empty_circuit);
+                let mut buf = vec![];
+                verifyingkey.write(&mut buf)?;
+                sled_db.insert("rlnv2-diff-register-vk", buf)?;
+                verifyingkey
+            }
+        };
+
+        // Read or build signal verifying key
+        let signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN, false).unwrap();
         let signal_empty_circuit =
             ZkCircuit::new(empty_witnesses(&signal_zkbin).unwrap(), &signal_zkbin);
 
@@ -416,6 +443,26 @@ impl EventGraph {
             }
         };
 
+        // Read or build slash verifying key
+        let slash_zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false).unwrap();
+        let slash_empty_circuit =
+            ZkCircuit::new(empty_witnesses(&slash_zkbin).unwrap(), &slash_zkbin);
+
+        let slash_vk = match sled_db.get("rlnv2-diff-slash-vk")? {
+            Some(vk) => {
+                let mut reader = Cursor::new(vk);
+                VerifyingKey::read(&mut reader, slash_empty_circuit)?
+            }
+            None => {
+                info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash VerifyingKey");
+                let verifyingkey = VerifyingKey::build(slash_zkbin.k, &slash_empty_circuit);
+                let mut buf = vec![];
+                verifyingkey.write(&mut buf)?;
+                sled_db.insert("rlnv2-diff-slash-vk", buf)?;
+                verifyingkey
+            }
+        };
+
         let broadcasted_ids = RwLock::new(HashSet::new());
         let event_pub = Publisher::new();
         let static_pub = Publisher::new();
@@ -449,7 +496,9 @@ impl EventGraph {
             synced: RwLock::new(false),
             deg_enabled: RwLock::new(false),
             deg_publisher: Publisher::new(),
+            register_vk,
             signal_vk,
+            slash_vk,
         });
 
         // Check if we have it in our DAG.
@@ -1285,8 +1334,8 @@ impl EventGraph {
         Ok(())
     }
 
-    pub async fn static_broadcast(&self, event: Event) -> Result<()> {
-        self.p2p.broadcast(&StaticPut(event)).await;
+    pub async fn static_broadcast(&self, event: Event, blob: Vec<u8>) -> Result<()> {
+        self.p2p.broadcast(&StaticPut(event, blob)).await;
         Ok(())
     }
 

+ 22 - 0
src/event_graph/proof/rlnv2-diff-register.zk

@@ -0,0 +1,22 @@
+k = 11;
+field = "pallas";
+
+constant "Rlnv2Diff_Register" {}
+
+witness "Rlnv2Diff_Register" {
+	Base identity_nullifier,
+	Base identity_trapdoor,
+	Base user_message_limit,
+	Base message_limit,
+}
+
+circuit "Rlnv2Diff_Register" {
+	identity_secret = poseidon_hash(identity_nullifier, identity_trapdoor);
+	identity_secret_hash = poseidon_hash(identity_secret, user_message_limit);
+	identity_commitment = poseidon_hash(identity_secret_hash);
+
+	less_than_strict(user_message_limit, message_limit);
+
+	constrain_instance(identity_commitment);
+	constrain_instance(user_message_limit);
+}

+ 0 - 0
src/event_graph/proofs/rlnv2-diff-signal.zk → src/event_graph/proof/rlnv2-diff-signal.zk


+ 0 - 0
src/event_graph/proofs/rlnv2-diff-slash.zk → src/event_graph/proof/rlnv2-diff-slash.zk


+ 45 - 14
src/event_graph/proto.rs

@@ -26,7 +26,10 @@ use std::{
     },
 };
 
-use darkfi_sdk::{crypto::poseidon_hash, pasta::pallas};
+use darkfi_sdk::{
+    crypto::{poseidon_hash, util::FieldElemAsStr},
+    pasta::{pallas, Fp},
+};
 use darkfi_serial::{
     async_trait, deserialize_async, deserialize_async_partial, SerialDecodable, SerialEncodable,
 };
@@ -146,7 +149,7 @@ impl_p2p_message!(EventPut, "EventGraph::EventPut", 0, 0, DEFAULT_METERING_CONFI
 /// A P2P message representing publishing an event of a static graph
 /// (most likely RLN_identities) on the network
 #[derive(Clone, SerialEncodable, SerialDecodable)]
-pub struct StaticPut(pub Event);
+pub struct StaticPut(pub Event, pub Vec<u8>);
 impl_p2p_message!(StaticPut, "EventGraph::StaticPut", 0, 0, DEFAULT_METERING_CONFIGURATION);
 
 /// A P2P message representing an event request
@@ -299,6 +302,9 @@ impl ProtocolEventGraph {
             let mut verification_failed = false;
             #[allow(clippy::never_loop)]
             loop {
+                if blob.is_empty() {
+                    break
+                }
                 let (proof, y, internal_nullifier, identity_root): (
                     Proof,
                     pallas::Base,
@@ -325,15 +331,15 @@ impl ProtocolEventGraph {
                 let public_inputs =
                     vec![identity_root, external_nullifier, x, y, internal_nullifier];
 
-                metadata.add_share(external_nullifier, internal_nullifier, x, y)?;
-
                 if metadata.is_duplicate(&external_nullifier, &internal_nullifier, &x, &y) {
-                    error!("[Signal] Duplicate Message!");
+                    error!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Duplicate Message!");
                     verification_failed = true;
                     break
                 }
 
+                info!("internal nullifier: {}", internal_nullifier.to_string());
                 if metadata.is_reused(&external_nullifier, &internal_nullifier) {
+                    info!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Metadata is reused.. slashing..");
                     let shares = metadata.get_shares(&external_nullifier, &internal_nullifier);
                     let _secret = sss_recover(&shares);
 
@@ -346,6 +352,9 @@ impl ProtocolEventGraph {
                     break
                 }
 
+                // At this point we can safely add the shares
+                metadata.add_share(external_nullifier, internal_nullifier, x, y)?;
+
                 info!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Verifying incoming Event RLN proof");
                 verification_failed =
                     proof.verify(&self.event_graph.signal_vk, &public_inputs).is_err();
@@ -354,7 +363,7 @@ impl ProtocolEventGraph {
             }
 
             if verification_failed {
-                error!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Incoming Event RLN proof verification failed");
+                error!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Incoming Event RLN Signaling proof verification failed");
                 continue
             }
 
@@ -611,21 +620,19 @@ impl ProtocolEventGraph {
         let mut bantimes = MovingWindow::new(WINDOW_EXPIRY_TIME);
 
         loop {
-            let event = match self.st_put_sub.receive().await {
-                Ok(v) => v.0.clone(),
+            let (event, blob) = match self.st_put_sub.receive().await {
+                Ok(v) => (v.0.clone(), v.1.clone()),
                 Err(_) => continue,
             };
             trace!(
-                 target: "event_graph::protocol::handle_event_put()",
-                 "Got EventPut: {} [{}]", event.id(), self.channel.address(),
+                 target: "event_graph::protocol::handle_static_put()",
+                 "Got StaticPut: {} [{}]", event.id(), self.channel.address(),
             );
 
-            info!("Received a static event: {:?}", event);
-
             // Check if node has finished syncing its DAG
             if !*self.event_graph.synced.read().await {
                 debug!(
-                    target: "event_graph::protocol::handle_event_put",
+                    target: "event_graph::protocol::handle_static_put",
                     "DAG is still syncing, skipping..."
                 );
                 continue
@@ -640,6 +647,30 @@ impl ProtocolEventGraph {
                 continue
             }
 
+            if !blob.is_empty() {
+                let (proof, user_msg_limit): (Proof, u64) = match deserialize_async_partial(&blob)
+                    .await
+                {
+                    Ok((v, _)) => v,
+                    Err(e) => {
+                        error!(target: "event_graph::protocol::handle_static_put()","[EVENTGRAPH] Failed deserializing event ephemeral data: {}", e);
+                        continue
+                    }
+                };
+                let commitment: Fp = match deserialize_async_partial(&event.content()).await {
+                    Ok((v, _)) => v,
+                    Err(e) => {
+                        error!(target: "event_graph::protocol::handle_static_put()","[EVENTGRAPH] Failed deserializing event ephemeral data: {}", e);
+                        continue
+                    }
+                };
+                let public_inputs = vec![commitment, user_msg_limit.into()];
+
+                if proof.verify(&self.event_graph.register_vk, &public_inputs).is_err() {
+                    error!(target: "event_graph::protocol::handle_static_put()", "[EVENTGRAPH] Incoming Event RLN Registration proof verification failed");
+                    continue
+                }
+            }
             // Check if event's parents are in the static DAG
             for parent in event.header.parents.iter() {
                 if *parent == NULL_ID {
@@ -679,7 +710,7 @@ impl ProtocolEventGraph {
             );
 
             self.event_graph.static_insert(&event).await?;
-            self.event_graph.static_broadcast(event).await?
+            self.event_graph.static_broadcast(event, blob).await?
         }
     }
 

+ 2 - 4
src/event_graph/util.rs

@@ -304,11 +304,9 @@ impl MessageMetadata {
         external_nullifier: &pallas::Base,
         internal_nullifier: &pallas::Base,
     ) -> bool {
-        let inner_map = self.data.get(external_nullifier);
-        if inner_map.is_some() {
-            return inner_map.unwrap().get(internal_nullifier).is_some()
+        if let Some(inner_map) = self.data.get(external_nullifier) {
+            return inner_map.get(internal_nullifier).is_some()
         }
-
         false
     }
 }