Преглед изворни кода

event_graph: proper distiction between registered and slashed RLN accounts

dasman пре 6 месеци
родитељ
комит
719db10f7d

+ 1 - 1
bin/darkirc/src/crypto/rln.rs

@@ -115,7 +115,7 @@ impl RlnIdentity {
         let public_inputs = vec![commitment, pallas::Base::from(self.user_message_limit)];
         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());
         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_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN, false)?;
         let register_circuit = ZkCircuit::new(witnesses, &register_zkbin);
         let register_circuit = ZkCircuit::new(witnesses, &register_zkbin);
 
 
         let proof =
         let proof =

+ 16 - 20
bin/darkirc/src/irc/client.rs

@@ -27,13 +27,17 @@ use std::{
 };
 };
 
 
 use darkfi::{
 use darkfi::{
-    event_graph::{proto::EventPut, Event, NULL_ID},
+    event_graph::{
+        proto::EventPut,
+        rln::{process_commitment, RLNNode},
+        Event, NULL_ID,
+    },
     system::Subscription,
     system::Subscription,
     zk::{empty_witnesses, Proof, ProvingKey, ZkCircuit},
     zk::{empty_witnesses, Proof, ProvingKey, ZkCircuit},
     zkas::ZkBinary,
     zkas::ZkBinary,
     Error, Result,
     Error, Result,
 };
 };
-use darkfi_sdk::pasta::{pallas, Fp};
+use darkfi_sdk::pasta::pallas;
 use darkfi_serial::{deserialize_async_partial, serialize_async};
 use darkfi_serial::{deserialize_async_partial, serialize_async};
 use futures::FutureExt;
 use futures::FutureExt;
 use sled_overlay::sled;
 use sled_overlay::sled;
@@ -43,7 +47,7 @@ use smol::{
     net::SocketAddr,
     net::SocketAddr,
     prelude::{AsyncRead, AsyncWrite},
     prelude::{AsyncRead, AsyncWrite},
 };
 };
-use tracing::{debug, error, info, warn};
+use tracing::{debug, error, warn};
 
 
 use super::{
 use super::{
     server::{IrcServer, MAX_MSG_LEN},
     server::{IrcServer, MAX_MSG_LEN},
@@ -363,7 +367,7 @@ impl Client {
                     }
                     }
 
 
                     // Update SMT
                     // Update SMT
-                    let fetched_rln_commitment: Fp = match deserialize_async_partial(r.content()).await
+                    let fetched_rln_commitment: RLNNode = match deserialize_async_partial(r.content()).await
                     {
                     {
                         Ok((v, _)) => v,
                         Ok((v, _)) => v,
                         Err(e) => {
                         Err(e) => {
@@ -371,10 +375,9 @@ impl Client {
                             continue
                             continue
                         }
                         }
                     };
                     };
-                    let commitment = vec![fetched_rln_commitment];
-                    let commitment: Vec<_> = commitment.into_iter().map(|l| (l, l)).collect();
+
                     let mut identities_tree = self.server.darkirc.event_graph.rln_identity_tree.write().await;
                     let mut identities_tree = self.server.darkirc.event_graph.rln_identity_tree.write().await;
-                    identities_tree.insert_batch(commitment)?;
+                    process_commitment(fetched_rln_commitment, &mut identities_tree)?;
                     drop(identities_tree);
                     drop(identities_tree);
 
 
                     // Mark the message as seen for this USER
                     // Mark the message as seen for this USER
@@ -416,7 +419,7 @@ impl Client {
         &self,
         &self,
         line: &str,
         line: &str,
         writer: &mut W,
         writer: &mut W,
-        args_queue: &mut VecDeque<OldPrivmsg>,
+        args_queue: &mut VecDeque<Privmsg>,
     ) -> Result<Option<Vec<Event>>>
     ) -> Result<Option<Vec<Event>>>
     where
     where
         W: AsyncWrite + Unpin,
         W: AsyncWrite + Unpin,
@@ -533,7 +536,7 @@ impl Client {
     }
     }
 
 
     // Internal helper function that creates a PRIVMSG from IRC client arguments
     // Internal helper function that creates a PRIVMSG from IRC client arguments
-    async fn args_to_privmsg(&self, args: String) -> OldPrivmsg {
+    async fn args_to_privmsg(&self, args: String) -> Privmsg {
         let nick = self.nickname.read().await.to_string();
         let nick = self.nickname.read().await.to_string();
         let channel = args.split_ascii_whitespace().next().unwrap().to_string();
         let channel = args.split_ascii_whitespace().next().unwrap().to_string();
         let msg_offset = args.find(':').unwrap() + 1;
         let msg_offset = args.find(':').unwrap() + 1;
@@ -541,18 +544,11 @@ impl Client {
 
 
         // Truncate messages longer than MAX_MSG_LEN
         // Truncate messages longer than MAX_MSG_LEN
         let msg = if msg.len() > MAX_MSG_LEN { msg.split_at(MAX_MSG_LEN).0 } else { msg };
         let msg = if msg.len() > MAX_MSG_LEN { msg.split_at(MAX_MSG_LEN).0 } else { msg };
+        Privmsg { version: 0, msg_type: 0, channel, nick, msg: msg.to_string() }
+    }
 
 
-        // 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,
-        };
-
+    // Internal helper function that creates an Event from PRIVMSG arguments
+    async fn privmsg_to_event(&self, mut privmsg: Privmsg) -> Event {
         // Encrypt the Privmsg if an encryption method is available.
         // Encrypt the Privmsg if an encryption method is available.
         self.server.try_encrypt(&mut privmsg).await;
         self.server.try_encrypt(&mut privmsg).await;
 
 

+ 9 - 8
bin/darkirc/src/irc/server.rs

@@ -19,14 +19,16 @@
 use std::{collections::HashMap, fs::File, io::BufReader, path::PathBuf, sync::Arc};
 use std::{collections::HashMap, fs::File, io::BufReader, path::PathBuf, sync::Arc};
 
 
 use darkfi::{
 use darkfi::{
-    event_graph::Event,
+    event_graph::{
+        rln::{process_commitment, RLNNode},
+        Event,
+    },
     system::{StoppableTask, StoppableTaskPtr, Subscription},
     system::{StoppableTask, StoppableTaskPtr, Subscription},
     util::path::expand_path,
     util::path::expand_path,
     zk::{empty_witnesses, ProvingKey, ZkCircuit},
     zk::{empty_witnesses, ProvingKey, ZkCircuit},
     zkas::ZkBinary,
     zkas::ZkBinary,
     Error, Result,
     Error, Result,
 };
 };
-use darkfi_sdk::pasta::Fp;
 use darkfi_serial::{deserialize_async, deserialize_async_partial};
 use darkfi_serial::{deserialize_async, deserialize_async_partial};
 use futures_rustls::{
 use futures_rustls::{
     rustls::{self, pki_types::PrivateKeyDer},
     rustls::{self, pki_types::PrivateKeyDer},
@@ -148,7 +150,7 @@ impl IrcServer {
         let server_store = darkirc.sled.open_tree("server_store")?;
         let server_store = darkirc.sled.open_tree("server_store")?;
 
 
         // Generate RLN proving and verifying keys, if needed
         // Generate RLN proving and verifying keys, if needed
-        let rln_register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN)?;
+        let rln_register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN, false)?;
         let rln_register_circuit =
         let rln_register_circuit =
             ZkCircuit::new(empty_witnesses(&rln_register_zkbin)?, &rln_register_zkbin);
             ZkCircuit::new(empty_witnesses(&rln_register_zkbin)?, &rln_register_zkbin);
 
 
@@ -161,7 +163,7 @@ impl IrcServer {
         }
         }
 
 
         // Generate RLN proving and verifying keys, if needed
         // Generate RLN proving and verifying keys, if needed
-        let rln_signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN)?;
+        let rln_signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN, false)?;
         let rln_signal_circuit =
         let rln_signal_circuit =
             ZkCircuit::new(empty_witnesses(&rln_signal_zkbin)?, &rln_signal_zkbin);
             ZkCircuit::new(empty_witnesses(&rln_signal_zkbin)?, &rln_signal_zkbin);
 
 
@@ -180,7 +182,8 @@ impl IrcServer {
 
 
         for event in events.iter() {
         for event in events.iter() {
             // info!("event: {}", event.id());
             // info!("event: {}", event.id());
-            let fetched_rln_commitment: Fp = match deserialize_async_partial(event.content()).await
+            let fetched_rln_commitment: RLNNode = match deserialize_async_partial(event.content())
+                .await
             {
             {
                 Ok((v, _)) => v,
                 Ok((v, _)) => v,
                 Err(e) => {
                 Err(e) => {
@@ -189,9 +192,7 @@ impl IrcServer {
                 }
                 }
             };
             };
 
 
-            let commitment = vec![fetched_rln_commitment];
-            let commitment: Vec<_> = commitment.into_iter().map(|l| (l, l)).collect();
-            identity_tree.insert_batch(commitment)?;
+            process_commitment(fetched_rln_commitment, &mut identity_tree)?;
         }
         }
 
 
         drop(identity_tree);
         drop(identity_tree);

+ 3 - 2
bin/darkirc/src/irc/services/nickserv.rs

@@ -19,7 +19,7 @@
 use std::{io::Cursor, str::SplitAsciiWhitespace, sync::Arc, time::UNIX_EPOCH};
 use std::{io::Cursor, str::SplitAsciiWhitespace, sync::Arc, time::UNIX_EPOCH};
 
 
 use darkfi::{
 use darkfi::{
-    event_graph::Event,
+    event_graph::{rln::RLNNode, Event},
     zk::{empty_witnesses, ProvingKey, ZkCircuit},
     zk::{empty_witnesses, ProvingKey, ZkCircuit},
     zkas::ZkBinary,
     zkas::ZkBinary,
     Error, Result,
     Error, Result,
@@ -211,11 +211,12 @@ impl NickServ {
 
 
         // Update SMT, DAG and broadcast
         // Update SMT, DAG and broadcast
         let rln_commitment = new_rln_identity.commitment();
         let rln_commitment = new_rln_identity.commitment();
+        let rln_commitment = RLNNode::Registration(rln_commitment);
         let evgr = &self.server.darkirc.event_graph;
         let evgr = &self.server.darkirc.event_graph;
         let event = Event::new_static(serialize_async(&rln_commitment).await, evgr).await;
         let event = Event::new_static(serialize_async(&rln_commitment).await, evgr).await;
 
 
         // Retrieve the register ZK proving key from the db
         // Retrieve the register ZK proving key from the db
-        let register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN)?;
+        let register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN, false)?;
         let register_circuit = ZkCircuit::new(empty_witnesses(&register_zkbin)?, &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 {
         let Some(proving_key) = self.server.server_store.get("rlnv2-diff-register-pk")? else {
             return Err(Error::DatabaseError(
             return Err(Error::DatabaseError(

+ 0 - 1
src/event_graph/event.rs

@@ -20,7 +20,6 @@ use std::{collections::HashSet, time::UNIX_EPOCH};
 
 
 use darkfi_serial::{async_trait, deserialize_async, Encodable, SerialDecodable, SerialEncodable};
 use darkfi_serial::{async_trait, deserialize_async, Encodable, SerialDecodable, SerialEncodable};
 use sled_overlay::{sled, SledTreeOverlay};
 use sled_overlay::{sled, SledTreeOverlay};
-use tracing::info;
 
 
 use crate::{event_graph::util::generate_genesis, Result};
 use crate::{event_graph::util::generate_genesis, Result};
 
 

+ 4 - 4
src/event_graph/mod.rs

@@ -46,10 +46,7 @@ use url::Url;
 use crate::{
 use crate::{
     event_graph::{
     event_graph::{
         proto::StaticPut,
         proto::StaticPut,
-        util::{
-            build_register_vk, build_signal_vk, build_slash_pk, build_slash_vk,
-            next_hour_timestamp, next_rotation_timestamp, replayer_log,
-        },
+        util::{next_hour_timestamp, next_rotation_timestamp, replayer_log},
     },
     },
     net::{channel::Channel, P2pPtr},
     net::{channel::Channel, P2pPtr},
     system::{msleep, Publisher, PublisherPtr, StoppableTask, StoppableTaskPtr, Subscription},
     system::{msleep, Publisher, PublisherPtr, StoppableTask, StoppableTaskPtr, Subscription},
@@ -74,6 +71,9 @@ pub use event::Event;
 pub mod proto;
 pub mod proto;
 use proto::{EventRep, EventReq, HeaderRep, HeaderReq, TipRep, TipReq};
 use proto::{EventRep, EventReq, HeaderRep, HeaderReq, TipRep, TipReq};
 
 
+pub mod rln;
+use rln::{build_register_vk, build_signal_vk, build_slash_pk, build_slash_vk};
+
 /// Utility functions
 /// Utility functions
 pub mod util;
 pub mod util;
 use util::{generate_genesis, millis_until_next_rotation};
 use util::{generate_genesis, millis_until_next_rotation};

+ 69 - 53
src/event_graph/proto.rs

@@ -28,7 +28,7 @@ use std::{
 
 
 use darkfi_sdk::{
 use darkfi_sdk::{
     crypto::{poseidon_hash, util::FieldElemAsStr},
     crypto::{poseidon_hash, util::FieldElemAsStr},
-    pasta::{pallas, Fp},
+    pasta::pallas,
 };
 };
 use darkfi_serial::{
 use darkfi_serial::{
     async_trait, deserialize_async, deserialize_async_partial, serialize_async, SerialDecodable,
     async_trait, deserialize_async, deserialize_async_partial, serialize_async, SerialDecodable,
@@ -37,11 +37,12 @@ use darkfi_serial::{
 use smol::Executor;
 use smol::Executor;
 use tracing::{debug, error, info, trace, warn};
 use tracing::{debug, error, info, trace, warn};
 
 
-use super::{event::Header, Event, EventGraphPtr, LayerUTips, NULL_ID, NULL_PARENTS};
+use super::{
+    event::Header,
+    rln::{closest_epoch, create_slash_proof, hash_event, sss_recover, MessageMetadata, RLNNode},
+    Event, EventGraphPtr, LayerUTips, NULL_ID, NULL_PARENTS,
+};
 use crate::{
 use crate::{
-    event_graph::util::{
-        closest_epoch, create_slash_proof, hash_event, sss_recover, MessageMetadata,
-    },
     impl_p2p_message,
     impl_p2p_message,
     net::{
     net::{
         metering::{MeteringConfiguration, DEFAULT_METERING_CONFIGURATION},
         metering::{MeteringConfiguration, DEFAULT_METERING_CONFIGURATION},
@@ -370,7 +371,12 @@ impl ProtocolEventGraph {
                         serialize_async(&(proof, secret, user_msg_limit, identity_root)).await;
                         serialize_async(&(proof, secret, user_msg_limit, identity_root)).await;
 
 
                     let evgr = &self.event_graph;
                     let evgr = &self.event_graph;
-                    let st_event = Event::new_static(vec![0, 1], evgr).await;
+                    let identity_secret_hash = poseidon_hash([secret, user_msg_limit.into()]);
+                    let identity_commitment = poseidon_hash([identity_secret_hash]);
+                    let rln_commitment = RLNNode::Slashing(identity_commitment);
+                    let st_event =
+                        Event::new_static(serialize_async(&rln_commitment).await, evgr).await;
+                    evgr.static_insert(&st_event).await?;
                     evgr.static_broadcast(st_event, blob).await?;
                     evgr.static_broadcast(st_event, blob).await?;
 
 
                     verification_failed = true;
                     verification_failed = true;
@@ -672,63 +678,73 @@ impl ProtocolEventGraph {
                 continue
                 continue
             }
             }
 
 
-            // Register
-            if !blob.is_empty() && !event.content().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()","[RLN] 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
-                    }
-                };
-                info!("registering account: {}", commitment.to_string());
-                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()", "[RLN] Incoming Event RLN Registration proof verification failed");
+            let rln_account: RLNNode = match deserialize_async_partial(&event.content()).await {
+                Ok((v, _)) => v,
+                Err(e) => {
+                    error!(target: "event_graph::protocol::handle_static_put()","[RLN] Failed deserializing event ephemeral data: {}", e);
                     continue
                     continue
                 }
                 }
+            };
+
+            if blob.is_empty() {
+                error!(target: "event_graph::protocol::handle_static_put()","[RLN] Failed to register/slash: Not enough data provided");
+                continue
             }
             }
+            match rln_account {
+                RLNNode::Registration(commitment) => {
+                    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()","[RLN] Failed deserializing event ephemeral data: {}", e);
+                            continue
+                        }
+                    };
 
 
-            // Slash
-            if event.content() == vec![0, 1] {
-                let (proof, secret, user_msg_limit, identity_root): (
-                    Proof,
-                    pallas::Base,
-                    u64,
-                    pallas::Base,
-                ) = match deserialize_async_partial(&blob).await {
-                    Ok((v, _)) => v,
-                    Err(e) => {
-                        error!(target: "event_graph::protocol::handle_static_put()","[RLN] Failed deserializing event ephemeral data: {}", e);
+                    info!("registering account: {:?}", commitment);
+                    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()", "[RLN] Incoming Event RLN Registration proof verification failed");
                         continue
                         continue
                     }
                     }
-                };
+                }
+                RLNNode::Slashing(commitment) => {
+                    let (proof, secret, user_msg_limit, identity_root): (
+                        Proof,
+                        pallas::Base,
+                        u64,
+                        pallas::Base,
+                    ) = match deserialize_async_partial(&blob).await {
+                        Ok((v, _)) => v,
+                        Err(e) => {
+                            error!(target: "event_graph::protocol::handle_static_put()","[RLN] Failed deserializing event ephemeral data: {}", e);
+                            continue
+                        }
+                    };
 
 
-                let public_inputs = vec![secret, pallas::Base::from(user_msg_limit), identity_root];
+                    let public_inputs =
+                        vec![secret, pallas::Base::from(user_msg_limit), identity_root];
 
 
-                if proof.verify(&self.event_graph.slash_vk, &public_inputs).is_err() {
-                    error!(target: "event_graph::protocol::handle_static_put()", "[RLN] Incoming Event RLN Slashing proof verification failed");
-                    continue
-                }
+                    if proof.verify(&self.event_graph.slash_vk, &public_inputs).is_err() {
+                        error!(target: "event_graph::protocol::handle_static_put()", "[RLN] Incoming Event RLN Slashing proof verification failed");
+                        continue
+                    }
 
 
-                let identity_secret_hash = poseidon_hash([secret, user_msg_limit.into()]);
-                let commitment = poseidon_hash([identity_secret_hash]);
-                info!("slashing account: {}", commitment.to_string());
-                let commitment = vec![commitment];
-                let commitment: Vec<_> = commitment.into_iter().map(|l| (l, l)).collect();
+                    let identity_secret_hash = poseidon_hash([secret, user_msg_limit.into()]);
+                    let rebuilt_commitment = poseidon_hash([identity_secret_hash]);
 
 
-                let mut rln_id_tree = self.event_graph.rln_identity_tree.write().await;
-                rln_id_tree.remove_leaves(commitment)?;
+                    assert_eq!(commitment, rebuilt_commitment);
+                    info!("slashing account: {}", rebuilt_commitment.to_string());
+                    let commitment = vec![rebuilt_commitment];
+                    let commitment: Vec<_> = commitment.into_iter().map(|l| (l, l)).collect();
+
+                    let mut rln_id_tree = self.event_graph.rln_identity_tree.write().await;
+                    rln_id_tree.remove_leaves(commitment)?;
+                }
             }
             }
 
 
             // Check if event's parents are in the static DAG
             // Check if event's parents are in the static DAG

+ 308 - 0
src/event_graph/rln.rs

@@ -0,0 +1,308 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2025 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::BTreeMap;
+
+use async_trait::async_trait;
+use darkfi_sdk::pasta::pallas;
+
+use std::io::Cursor;
+
+use darkfi_sdk::crypto::{pasta_prelude::FromUniformBytes, poseidon_hash, smt::SmtMemoryFp};
+use darkfi_serial::{FutAsyncWriteExt, SerialDecodable, SerialEncodable};
+use halo2_proofs::{arithmetic::Field, circuit::Value};
+use rand::rngs::OsRng;
+use sled_overlay::sled;
+use tracing::info;
+
+use crate::{
+    event_graph::Event,
+    zk::{empty_witnesses, Proof, ProvingKey, VerifyingKey, Witness, ZkCircuit},
+    zkas::ZkBinary,
+    Result,
+};
+
+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");
+
+/// RLN epoch genesis in millis
+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
+
+/// Hash message/event modulo `Fp`
+pub fn hash_event(event: &Event) -> pallas::Base {
+    let mut buf = [0u8; 64];
+    buf[..blake3::OUT_LEN].copy_from_slice(event.header.id().as_bytes());
+    pallas::Base::from_uniform_bytes(&buf)
+}
+
+/// Find closest epoch to given timestamp
+pub fn closest_epoch(timestamp: u64) -> u64 {
+    let time_diff = timestamp - RLN_GENESIS;
+    let epoch_idx = time_diff as f64 / RLN_EPOCH_LEN as f64;
+    let rounded = epoch_idx.round() as i64;
+    RLN_GENESIS + (rounded * RLN_EPOCH_LEN as i64) as u64
+}
+
+#[derive(Debug, Clone)]
+struct ShareData {
+    pub x_shares: Vec<pallas::Base>,
+    pub y_shares: Vec<pallas::Base>,
+}
+
+impl ShareData {
+    fn new() -> Self {
+        Self { x_shares: vec![], y_shares: vec![] }
+    }
+}
+
+#[derive(Debug, Default)]
+pub struct MessageMetadata {
+    data: BTreeMap<pallas::Base, BTreeMap<pallas::Base, ShareData>>,
+}
+
+impl MessageMetadata {
+    pub fn new() -> Self {
+        Self { data: BTreeMap::new() }
+    }
+
+    pub fn add_share(
+        &mut self,
+        external_nullifier: pallas::Base,
+        internal_nullifier: pallas::Base,
+        x: pallas::Base,
+        y: pallas::Base,
+    ) -> Result<()> {
+        let inner_map = self.data.entry(external_nullifier).or_insert_with(BTreeMap::new);
+        let share_data = inner_map.entry(internal_nullifier).or_insert_with(ShareData::new);
+
+        share_data.x_shares.push(x);
+        share_data.y_shares.push(y);
+
+        Ok(())
+    }
+
+    pub fn get_shares(
+        &self,
+        external_nullifier: &pallas::Base,
+        internal_nullifier: &pallas::Base,
+    ) -> Vec<(pallas::Base, pallas::Base)> {
+        if let Some(inner_map) = self.data.get(external_nullifier) {
+            if let Some(share_data) = inner_map.get(internal_nullifier) {
+                return share_data
+                    .x_shares
+                    .iter()
+                    .cloned()
+                    .zip(share_data.y_shares.iter().cloned())
+                    .collect()
+            }
+        }
+
+        vec![]
+    }
+
+    /// Check if the recieved message and its metadata are duplicated
+    pub fn is_duplicate(
+        &self,
+        external_nullifier: &pallas::Base,
+        internal_nullifier: &pallas::Base,
+        x: &pallas::Base,
+        y: &pallas::Base,
+    ) -> bool {
+        if let Some(inner_map) = self.data.get(external_nullifier) {
+            if let Some(share_data) = inner_map.get(internal_nullifier) {
+                return share_data.x_shares.contains(x) && share_data.y_shares.contains(y);
+            }
+        }
+
+        false
+    }
+
+    /// Check if the message has reused the nullifiers
+    pub fn is_reused(
+        &self,
+        external_nullifier: &pallas::Base,
+        internal_nullifier: &pallas::Base,
+    ) -> bool {
+        if let Some(inner_map) = self.data.get(external_nullifier) {
+            return inner_map.get(internal_nullifier).is_some()
+        }
+        false
+    }
+}
+
+#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
+pub enum RLNNode {
+    Registration(pallas::Base),
+    Slashing(pallas::Base),
+}
+
+pub fn process_commitment(node: RLNNode, identity_tree: &mut SmtMemoryFp) -> Result<()> {
+    match node {
+        RLNNode::Registration(commitment) => {
+            // Add to smt
+            let commitment = vec![commitment];
+            let commitment: Vec<_> = commitment.into_iter().map(|l| (l, l)).collect();
+            identity_tree.insert_batch(commitment)?;
+        }
+        RLNNode::Slashing(commitment) => {
+            // Remove from smt
+            let commitment = vec![commitment];
+            let commitment: Vec<_> = commitment.into_iter().map(|l| (l, l)).collect();
+            identity_tree.remove_leaves(commitment)?;
+        }
+    }
+
+    Ok(())
+}
+
+pub fn create_slash_proof(
+    secret: pallas::Base,
+    user_msg_limit: u64,
+    identities_tree: &mut SmtMemoryFp,
+    slash_pk: &ProvingKey,
+) -> Result<(Proof, pallas::Base)> {
+    let identity_secret_hash = poseidon_hash([secret, user_msg_limit.into()]);
+    let commitment = poseidon_hash([identity_secret_hash]);
+
+    let identity_root = identities_tree.root();
+    let identity_path = identities_tree.prove_membership(&commitment);
+    // TODO: Delete me later
+    assert!(identity_path.verify(&identity_root, &commitment, &commitment));
+
+    let witnesses = vec![
+        Witness::Base(Value::known(secret)),
+        Witness::Base(Value::known(pallas::Base::from(user_msg_limit))),
+        Witness::SparseMerklePath(Value::known(identity_path.path)),
+    ];
+
+    let public_inputs = vec![secret, pallas::Base::from(user_msg_limit), identity_root];
+
+    let slash_zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false)?;
+    let slash_circuit = ZkCircuit::new(witnesses, &slash_zkbin);
+
+    let proof = Proof::create(&slash_pk, &[slash_circuit], &public_inputs, &mut OsRng).unwrap();
+
+    Ok((proof, identity_root))
+}
+
+/// Recover secret using Shamir's secret sharing scheme
+pub fn sss_recover(shares: &[(pallas::Base, pallas::Base)]) -> pallas::Base {
+    let mut secret = pallas::Base::zero();
+    for (j, share_j) in shares.iter().enumerate() {
+        let mut prod = pallas::Base::one();
+        for (i, share_i) in shares.iter().enumerate() {
+            if i != j {
+                prod *= share_i.0 * (share_i.0 - share_j.0).invert().unwrap();
+            }
+        }
+
+        prod *= share_j.1;
+        secret += prod;
+    }
+
+    secret
+}
+
+/// Helper function to read or build register verifying key
+pub(super) fn build_register_vk(sled_db: &sled::Db) -> Result<VerifyingKey> {
+    let register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN, false).unwrap();
+    let register_empty_circuit =
+        ZkCircuit::new(empty_witnesses(&register_zkbin).unwrap(), &register_zkbin);
+
+    match sled_db.get("rlnv2-diff-register-vk")? {
+        Some(vk) => {
+            let mut reader = Cursor::new(vk);
+            Ok(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)?;
+            Ok(verifyingkey)
+        }
+    }
+}
+
+/// Helper function to read or build signal verifying key
+pub(super) fn build_signal_vk(sled_db: &sled::Db) -> Result<VerifyingKey> {
+    let signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN, false).unwrap();
+    let signal_empty_circuit =
+        ZkCircuit::new(empty_witnesses(&signal_zkbin).unwrap(), &signal_zkbin);
+
+    match sled_db.get("rlnv2-diff-signal-vk")? {
+        Some(vk) => {
+            let mut reader = Cursor::new(vk);
+            Ok(VerifyingKey::read(&mut reader, signal_empty_circuit)?)
+        }
+        None => {
+            info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Signal VerifyingKey");
+            let verifyingkey = VerifyingKey::build(signal_zkbin.k, &signal_empty_circuit);
+            let mut buf = vec![];
+            verifyingkey.write(&mut buf)?;
+            sled_db.insert("rlnv2-diff-signal-vk", buf)?;
+            Ok(verifyingkey)
+        }
+    }
+}
+
+/// Helper function to read or build slash proving key
+pub(super) fn build_slash_pk(sled_db: &sled::Db) -> Result<ProvingKey> {
+    let slash_zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false).unwrap();
+    let slash_empty_circuit = ZkCircuit::new(empty_witnesses(&slash_zkbin).unwrap(), &slash_zkbin);
+
+    match sled_db.get("rlnv2-diff-slash-pk")? {
+        Some(pk) => {
+            let mut reader = Cursor::new(pk);
+            Ok(ProvingKey::read(&mut reader, slash_empty_circuit)?)
+        }
+        None => {
+            info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash ProvingKey");
+            let provingkey = ProvingKey::build(slash_zkbin.k, &slash_empty_circuit);
+            let mut buf = vec![];
+            provingkey.write(&mut buf)?;
+            sled_db.insert("rlnv2-diff-slash-pk", buf)?;
+            Ok(provingkey)
+        }
+    }
+}
+
+/// Helper function to read or build slash verifying key
+pub(super) fn build_slash_vk(sled_db: &sled::Db) -> Result<VerifyingKey> {
+    let slash_zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false).unwrap();
+    let slash_empty_circuit = ZkCircuit::new(empty_witnesses(&slash_zkbin).unwrap(), &slash_zkbin);
+
+    match sled_db.get("rlnv2-diff-slash-vk")? {
+        Some(vk) => {
+            let mut reader = Cursor::new(vk);
+            Ok(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)?;
+            Ok(verifyingkey)
+        }
+    }
+}

+ 3 - 256
src/event_graph/util.rs

@@ -17,29 +17,21 @@
  */
  */
 
 
 use std::{
 use std::{
-    collections::{BTreeMap, HashMap},
+    collections::HashMap,
     fs::{self, File, OpenOptions},
     fs::{self, File, OpenOptions},
-    io::{Cursor, Write},
+    io::Write,
     path::Path,
     path::Path,
     time::UNIX_EPOCH,
     time::UNIX_EPOCH,
 };
 };
 
 
-use darkfi_sdk::{
-    crypto::{pasta_prelude::FromUniformBytes, poseidon_hash, smt::SmtMemoryFp},
-    pasta::pallas,
-};
 use darkfi_serial::{deserialize, deserialize_async, serialize};
 use darkfi_serial::{deserialize, deserialize_async, serialize};
-use halo2_proofs::{arithmetic::Field, circuit::Value};
-use rand::rngs::OsRng;
 use sled_overlay::sled;
 use sled_overlay::sled;
 use tinyjson::JsonValue;
 use tinyjson::JsonValue;
-use tracing::{error, info};
+use tracing::error;
 
 
 use crate::{
 use crate::{
     event_graph::{Event, GENESIS_CONTENTS, INITIAL_GENESIS, NULL_ID, N_EVENT_PARENTS},
     event_graph::{Event, GENESIS_CONTENTS, INITIAL_GENESIS, NULL_ID, N_EVENT_PARENTS},
     util::{encoding::base64, file::load_file},
     util::{encoding::base64, file::load_file},
-    zk::{empty_witnesses, Proof, ProvingKey, VerifyingKey, Witness, ZkCircuit},
-    zkas::ZkBinary,
     Result,
     Result,
 };
 };
 
 
@@ -51,15 +43,6 @@ use crate::rpc::{
 
 
 use super::event::Header;
 use super::event::Header;
 
 
-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");
-
-/// RLN epoch genesis in millis
-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
-
 /// MilliSeconds in an hour
 /// MilliSeconds in an hour
 pub(super) const HOUR: i64 = 3_600_000;
 pub(super) const HOUR: i64 = 3_600_000;
 
 
@@ -216,242 +199,6 @@ pub async fn recreate_from_replayer_log(datastore: &Path) -> JsonResult {
     JsonResponse::new(result, 1).into()
     JsonResponse::new(result, 1).into()
 }
 }
 
 
-/// Hash message/event modulo `Fp`
-pub fn hash_event(event: &Event) -> pallas::Base {
-    let mut buf = [0u8; 64];
-    buf[..blake3::OUT_LEN].copy_from_slice(event.header.id().as_bytes());
-    pallas::Base::from_uniform_bytes(&buf)
-}
-
-/// Find closest epoch to given timestamp
-pub fn closest_epoch(timestamp: u64) -> u64 {
-    let time_diff = timestamp - RLN_GENESIS;
-    let epoch_idx = time_diff as f64 / RLN_EPOCH_LEN as f64;
-    let rounded = epoch_idx.round() as i64;
-    RLN_GENESIS + (rounded * RLN_EPOCH_LEN as i64) as u64
-}
-
-#[derive(Debug, Clone)]
-struct ShareData {
-    pub x_shares: Vec<pallas::Base>,
-    pub y_shares: Vec<pallas::Base>,
-}
-
-impl ShareData {
-    fn new() -> Self {
-        Self { x_shares: vec![], y_shares: vec![] }
-    }
-}
-
-#[derive(Debug, Default)]
-pub struct MessageMetadata {
-    data: BTreeMap<pallas::Base, BTreeMap<pallas::Base, ShareData>>,
-}
-
-impl MessageMetadata {
-    pub fn new() -> Self {
-        Self { data: BTreeMap::new() }
-    }
-
-    pub fn add_share(
-        &mut self,
-        external_nullifier: pallas::Base,
-        internal_nullifier: pallas::Base,
-        x: pallas::Base,
-        y: pallas::Base,
-    ) -> Result<()> {
-        let inner_map = self.data.entry(external_nullifier).or_insert_with(BTreeMap::new);
-        let share_data = inner_map.entry(internal_nullifier).or_insert_with(ShareData::new);
-
-        share_data.x_shares.push(x);
-        share_data.y_shares.push(y);
-
-        Ok(())
-    }
-
-    pub fn get_shares(
-        &self,
-        external_nullifier: &pallas::Base,
-        internal_nullifier: &pallas::Base,
-    ) -> Vec<(pallas::Base, pallas::Base)> {
-        if let Some(inner_map) = self.data.get(external_nullifier) {
-            if let Some(share_data) = inner_map.get(internal_nullifier) {
-                return share_data
-                    .x_shares
-                    .iter()
-                    .cloned()
-                    .zip(share_data.y_shares.iter().cloned())
-                    .collect()
-            }
-        }
-
-        vec![]
-    }
-
-    /// Check if the recieved message and its metadata are duplicated
-    pub fn is_duplicate(
-        &self,
-        external_nullifier: &pallas::Base,
-        internal_nullifier: &pallas::Base,
-        x: &pallas::Base,
-        y: &pallas::Base,
-    ) -> bool {
-        if let Some(inner_map) = self.data.get(external_nullifier) {
-            if let Some(share_data) = inner_map.get(internal_nullifier) {
-                return share_data.x_shares.contains(x) && share_data.y_shares.contains(y);
-            }
-        }
-
-        false
-    }
-
-    /// Check if the message has reused the nullifiers
-    pub fn is_reused(
-        &self,
-        external_nullifier: &pallas::Base,
-        internal_nullifier: &pallas::Base,
-    ) -> bool {
-        if let Some(inner_map) = self.data.get(external_nullifier) {
-            return inner_map.get(internal_nullifier).is_some()
-        }
-        false
-    }
-}
-
-pub fn create_slash_proof(
-    secret: pallas::Base,
-    user_msg_limit: u64,
-    identities_tree: &mut SmtMemoryFp,
-    slash_pk: &ProvingKey,
-) -> Result<(Proof, pallas::Base)> {
-    let identity_secret_hash = poseidon_hash([secret, user_msg_limit.into()]);
-    let commitment = poseidon_hash([identity_secret_hash]);
-
-    let identity_root = identities_tree.root();
-    let identity_path = identities_tree.prove_membership(&commitment);
-    // TODO: Delete me later
-    assert!(identity_path.verify(&identity_root, &commitment, &commitment));
-
-    let witnesses = vec![
-        Witness::Base(Value::known(secret)),
-        Witness::Base(Value::known(pallas::Base::from(user_msg_limit))),
-        Witness::SparseMerklePath(Value::known(identity_path.path)),
-    ];
-
-    let public_inputs = vec![secret, pallas::Base::from(user_msg_limit), identity_root];
-
-    let slash_zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false)?;
-    let slash_circuit = ZkCircuit::new(witnesses, &slash_zkbin);
-
-    let proof = Proof::create(&slash_pk, &[slash_circuit], &public_inputs, &mut OsRng).unwrap();
-
-    Ok((proof, identity_root))
-}
-
-/// Recover secret using Shamir's secret sharing scheme
-pub fn sss_recover(shares: &[(pallas::Base, pallas::Base)]) -> pallas::Base {
-    let mut secret = pallas::Base::zero();
-    for (j, share_j) in shares.iter().enumerate() {
-        let mut prod = pallas::Base::one();
-        for (i, share_i) in shares.iter().enumerate() {
-            if i != j {
-                prod *= share_i.0 * (share_i.0 - share_j.0).invert().unwrap();
-            }
-        }
-
-        prod *= share_j.1;
-        secret += prod;
-    }
-
-    secret
-}
-
-/// Helper function to read or build register verifying key
-pub(super) fn build_register_vk(sled_db: &sled::Db) -> Result<VerifyingKey> {
-    let register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN, false).unwrap();
-    let register_empty_circuit =
-        ZkCircuit::new(empty_witnesses(&register_zkbin).unwrap(), &register_zkbin);
-
-    match sled_db.get("rlnv2-diff-register-vk")? {
-        Some(vk) => {
-            let mut reader = Cursor::new(vk);
-            Ok(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)?;
-            Ok(verifyingkey)
-        }
-    }
-}
-
-/// Helper function to read or build signal verifying key
-pub(super) fn build_signal_vk(sled_db: &sled::Db) -> Result<VerifyingKey> {
-    let signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN, false).unwrap();
-    let signal_empty_circuit =
-        ZkCircuit::new(empty_witnesses(&signal_zkbin).unwrap(), &signal_zkbin);
-
-    match sled_db.get("rlnv2-diff-signal-vk")? {
-        Some(vk) => {
-            let mut reader = Cursor::new(vk);
-            Ok(VerifyingKey::read(&mut reader, signal_empty_circuit)?)
-        }
-        None => {
-            info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Signal VerifyingKey");
-            let verifyingkey = VerifyingKey::build(signal_zkbin.k, &signal_empty_circuit);
-            let mut buf = vec![];
-            verifyingkey.write(&mut buf)?;
-            sled_db.insert("rlnv2-diff-signal-vk", buf)?;
-            Ok(verifyingkey)
-        }
-    }
-}
-
-/// Helper function to read or build slash proving key
-pub(super) fn build_slash_pk(sled_db: &sled::Db) -> Result<ProvingKey> {
-    let slash_zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false).unwrap();
-    let slash_empty_circuit = ZkCircuit::new(empty_witnesses(&slash_zkbin).unwrap(), &slash_zkbin);
-
-    match sled_db.get("rlnv2-diff-slash-pk")? {
-        Some(pk) => {
-            let mut reader = Cursor::new(pk);
-            Ok(ProvingKey::read(&mut reader, slash_empty_circuit)?)
-        }
-        None => {
-            info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash ProvingKey");
-            let provingkey = ProvingKey::build(slash_zkbin.k, &slash_empty_circuit);
-            let mut buf = vec![];
-            provingkey.write(&mut buf)?;
-            sled_db.insert("rlnv2-diff-slash-pk", buf)?;
-            Ok(provingkey)
-        }
-    }
-}
-
-/// Helper function to read or build slash verifying key
-pub(super) fn build_slash_vk(sled_db: &sled::Db) -> Result<VerifyingKey> {
-    let slash_zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false).unwrap();
-    let slash_empty_circuit = ZkCircuit::new(empty_witnesses(&slash_zkbin).unwrap(), &slash_zkbin);
-
-    match sled_db.get("rlnv2-diff-slash-vk")? {
-        Some(vk) => {
-            let mut reader = Cursor::new(vk);
-            Ok(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)?;
-            Ok(verifyingkey)
-        }
-    }
-}
-
 #[cfg(test)]
 #[cfg(test)]
 mod tests {
 mod tests {
     use super::*;
     use super::*;