Procházet zdrojové kódy

event_graph: implement slash zk circuit utilizing remove_leaves()

dasman před 6 měsíci
rodič
revize
47435c8300

+ 4 - 6
bin/darkirc/src/crypto/rln.rs

@@ -47,11 +47,9 @@ pub const RLN2_REGISTER_ZKBIN: &[u8] =
     include_bytes!("../../../../src/event_graph/proof/rlnv2-diff-register.zk.bin");
     include_bytes!("../../../../src/event_graph/proof/rlnv2-diff-register.zk.bin");
 pub const RLN2_SIGNAL_ZKBIN: &[u8] =
 pub const RLN2_SIGNAL_ZKBIN: &[u8] =
     include_bytes!("../../../../src/event_graph/proof/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/proof/rlnv2-diff-slash.zk.bin");
 
 
-/// TODO: this should be configurable
-pub const MAX_MSG_LIMIT: u64 = 20;
+/// TODO: this is arbitrary it should be based on stake
+pub const MAX_MSG_LIMIT: u64 = 100;
 
 
 /// Find closest epoch to given timestamp
 /// Find closest epoch to given timestamp
 pub fn closest_epoch(timestamp: u64) -> u64 {
 pub fn closest_epoch(timestamp: u64) -> u64 {
@@ -135,7 +133,7 @@ impl RlnIdentity {
         event: &Event,
         event: &Event,
         identity_tree: &SmtMemoryFp,
         identity_tree: &SmtMemoryFp,
         signal_pk: &ProvingKey,
         signal_pk: &ProvingKey,
-    ) -> Result<(Proof, pallas::Base, pallas::Base, pallas::Base)> {
+    ) -> Result<(Proof, pallas::Base, pallas::Base, u64)> {
         // 1. Construct share
         // 1. Construct share
         let rln_app_identifier = pallas::Base::from(1000);
         let rln_app_identifier = pallas::Base::from(1000);
         let epoch = pallas::Base::from(closest_epoch(event.header.timestamp));
         let epoch = pallas::Base::from(closest_epoch(event.header.timestamp));
@@ -173,7 +171,7 @@ impl RlnIdentity {
         let signal_circuit = ZkCircuit::new(witnesses.clone(), &signal_zkbin);
         let signal_circuit = ZkCircuit::new(witnesses.clone(), &signal_zkbin);
 
 
         let proof = Proof::create(signal_pk, &[signal_circuit], &public_inputs, &mut OsRng)?;
         let proof = Proof::create(signal_pk, &[signal_circuit], &public_inputs, &mut OsRng)?;
-        Ok((proof, y, internal_nullifier, identity_root))
+        Ok((proof, y, internal_nullifier, self.user_message_limit))
         // Ok((proof, public_inputs))
         // Ok((proof, public_inputs))
     }
     }
 }
 }

+ 7 - 6
bin/darkirc/src/irc/client.rs

@@ -223,17 +223,17 @@ impl Client {
 
 
                                         rln_identity.message_id += 1;
                                         rln_identity.message_id += 1;
 
 
-                                        let (proof, y, internal_nullifier, identity_root) = match self.create_rln_signal_proof(&rln_identity, &event).await {
+                                        let (proof, y, internal_nullifier, user_msg_limit) = match self.create_rln_signal_proof(&rln_identity, &event).await {
                                             Ok(v) => v,
                                             Ok(v) => v,
                                             Err(e) => {
                                             Err(e) => {
                                                 // TODO: Send a message to the IRC client telling that sending went wrong
                                                 // TODO: Send a message to the IRC client telling that sending went wrong
                                                 error!("[IRC CLIENT] Failed creating RLN signal proof: {e}");
                                                 error!("[IRC CLIENT] Failed creating RLN signal proof: {e}");
                                                 // Just use an empty "proof"
                                                 // Just use an empty "proof"
-                                                (Proof::new(vec![]), pallas::Base::from(0), pallas::Base::from(0), pallas::Base::from(0))
+                                                (Proof::new(vec![]), pallas::Base::from(0), pallas::Base::from(0), 0)
                                             }
                                             }
                                         };
                                         };
 
 
-                                        let blob = serialize_async(&(proof, y, internal_nullifier, identity_root)).await;
+                                        let blob = serialize_async(&(proof, y, internal_nullifier, user_msg_limit)).await;
 
 
                                         self.server.darkirc.p2p.broadcast(&EventPut(event, blob)).await;
                                         self.server.darkirc.p2p.broadcast(&EventPut(event, blob)).await;
                                     } else {
                                     } else {
@@ -363,7 +363,6 @@ impl Client {
                     }
                     }
 
 
                     // Update SMT
                     // Update SMT
-                    let mut identities_tree = self.server.rln_identity_tree.write().await;
                     let fetched_rln_commitment: Fp = match deserialize_async_partial(r.content()).await
                     let fetched_rln_commitment: Fp = match deserialize_async_partial(r.content()).await
                     {
                     {
                         Ok((v, _)) => v,
                         Ok((v, _)) => v,
@@ -374,7 +373,9 @@ impl Client {
                     };
                     };
                     let commitment = vec![fetched_rln_commitment];
                     let commitment = vec![fetched_rln_commitment];
                     let commitment: Vec<_> = commitment.into_iter().map(|l| (l, l)).collect();
                     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;
                     identities_tree.insert_batch(commitment)?;
                     identities_tree.insert_batch(commitment)?;
+                    drop(identities_tree);
 
 
                     // Mark the message as seen for this USER
                     // Mark the message as seen for this USER
                     if let Err(e) = self.mark_seen(&event_id).await {
                     if let Err(e) = self.mark_seen(&event_id).await {
@@ -593,8 +594,8 @@ impl Client {
         &self,
         &self,
         rln_identity: &RlnIdentity,
         rln_identity: &RlnIdentity,
         event: &Event,
         event: &Event,
-    ) -> Result<(Proof, pallas::Base, pallas::Base, pallas::Base)> {
-        let identity_tree = self.server.rln_identity_tree.read().await;
+    ) -> Result<(Proof, pallas::Base, pallas::Base, u64)> {
+        let identity_tree = self.server.darkirc.event_graph.rln_identity_tree.read().await;
 
 
         // Retrieve the ZK proving key from the db
         // Retrieve the ZK proving key from the db
         let signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN, false)?;
         let signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN, false)?;

+ 5 - 51
bin/darkirc/src/irc/server.rs

@@ -26,10 +26,7 @@ use darkfi::{
     zkas::ZkBinary,
     zkas::ZkBinary,
     Error, Result,
     Error, Result,
 };
 };
-use darkfi_sdk::{
-    crypto::smt::{MemoryStorageFp, PoseidonFp, SmtMemoryFp, EMPTY_NODES_FP},
-    pasta::Fp,
-};
+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},
@@ -53,7 +50,7 @@ use super::{
 };
 };
 use crate::{
 use crate::{
     crypto::{
     crypto::{
-        rln::{RlnIdentity, RLN2_REGISTER_ZKBIN, RLN2_SIGNAL_ZKBIN, RLN2_SLASH_ZKBIN},
+        rln::{RlnIdentity, RLN2_REGISTER_ZKBIN, RLN2_SIGNAL_ZKBIN},
         saltbox,
         saltbox,
     },
     },
     settings::{
     settings::{
@@ -93,8 +90,6 @@ pub struct IrcServer {
     pub password: String,
     pub password: String,
     /// Persistent server storage
     /// Persistent server storage
     pub server_store: sled::Tree,
     pub server_store: sled::Tree,
-    /// RLN identity storage
-    pub rln_identity_tree: RwLock<SmtMemoryFp>,
 }
 }
 
 
 impl IrcServer {
 impl IrcServer {
@@ -151,9 +146,6 @@ impl IrcServer {
 
 
         // Open persistent dbs
         // Open persistent dbs
         let server_store = darkirc.sled.open_tree("server_store")?;
         let server_store = darkirc.sled.open_tree("server_store")?;
-        let hasher = PoseidonFp::new();
-        let store = MemoryStorageFp::new();
-        let mut identity_tree = SmtMemoryFp::new(store, hasher.clone(), &EMPTY_NODES_FP);
 
 
         // 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)?;
@@ -168,14 +160,6 @@ impl IrcServer {
             server_store.insert("rlnv2-diff-register-pk", 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
         // 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)?;
         let rln_signal_circuit =
         let rln_signal_circuit =
@@ -189,39 +173,8 @@ impl IrcServer {
             server_store.insert("rlnv2-diff-signal-pk", buf)?;
             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)?;
-        // }
-
-        // 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 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
         // Construct SMT from static DAG
+        let mut identity_tree = darkirc.event_graph.rln_identity_tree.write().await;
         let mut events = darkirc.event_graph.static_fetch_all().await?;
         let mut events = darkirc.event_graph.static_fetch_all().await?;
         events.sort_by(|a, b| a.header.timestamp.cmp(&b.header.timestamp));
         events.sort_by(|a, b| a.header.timestamp.cmp(&b.header.timestamp));
 
 
@@ -241,6 +194,8 @@ impl IrcServer {
             identity_tree.insert_batch(commitment)?;
             identity_tree.insert_batch(commitment)?;
         }
         }
 
 
+        drop(identity_tree);
+
         // Set the default RLN account if any
         // Set the default RLN account if any
         let default_db = darkirc.sled.open_tree(format!("{}default", ACCOUNTS_DB_PREFIX))?;
         let default_db = darkirc.sled.open_tree(format!("{}default", ACCOUNTS_DB_PREFIX))?;
         let rln_identity = if !default_db.is_empty() {
         let rln_identity = if !default_db.is_empty() {
@@ -264,7 +219,6 @@ impl IrcServer {
             clients: Mutex::new(HashMap::new()),
             clients: Mutex::new(HashMap::new()),
             password,
             password,
             server_store,
             server_store,
-            rln_identity_tree: RwLock::new(identity_tree),
         });
         });
 
 
         // Load any channel/contact configuration.
         // Load any channel/contact configuration.

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

@@ -214,8 +214,6 @@ impl NickServ {
         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;
 
 
-        let mut identity_tree = self.server.rln_identity_tree.write().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)?;
         let register_circuit = ZkCircuit::new(empty_witnesses(&register_zkbin)?, &register_zkbin);
         let register_circuit = ZkCircuit::new(empty_witnesses(&register_zkbin)?, &register_zkbin);
@@ -226,12 +224,14 @@ impl NickServ {
         };
         };
         let mut reader = Cursor::new(proving_key);
         let mut reader = Cursor::new(proving_key);
         let proving_key = ProvingKey::read(&mut reader, register_circuit)?;
         let proving_key = ProvingKey::read(&mut reader, register_circuit)?;
+        let mut identity_tree = self.server.darkirc.event_graph.rln_identity_tree.write().await;
 
 
         let proof =
         let proof =
             new_rln_identity.create_register_proof(&event, &mut identity_tree, &proving_key)?;
             new_rln_identity.create_register_proof(&event, &mut identity_tree, &proving_key)?;
 
 
-        let blob = serialize_async(&(proof, user_msg_limit)).await;
+        drop(identity_tree);
 
 
+        let blob = serialize_async(&(proof, user_msg_limit)).await;
         evgr.static_insert(&event).await?;
         evgr.static_insert(&event).await?;
         evgr.static_broadcast(event, blob).await?;
         evgr.static_broadcast(event, blob).await?;
 
 

+ 19 - 66
src/event_graph/mod.rs

@@ -19,7 +19,6 @@
 // use async_std::stream::from_iter;
 // use async_std::stream::from_iter;
 use std::{
 use std::{
     collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque},
     collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque},
-    io::Cursor,
     path::PathBuf,
     path::PathBuf,
     str::FromStr,
     str::FromStr,
     sync::Arc,
     sync::Arc,
@@ -27,6 +26,7 @@ use std::{
 
 
 // use futures::stream::FuturesOrdered;
 // use futures::stream::FuturesOrdered;
 use blake3::Hash;
 use blake3::Hash;
+use darkfi_sdk::crypto::smt::{MemoryStorageFp, PoseidonFp, SmtMemoryFp, EMPTY_NODES_FP};
 use darkfi_serial::{deserialize_async, serialize_async};
 use darkfi_serial::{deserialize_async, serialize_async};
 use event::Header;
 use event::Header;
 use futures::{
 use futures::{
@@ -46,12 +46,14 @@ use url::Url;
 use crate::{
 use crate::{
     event_graph::{
     event_graph::{
         proto::StaticPut,
         proto::StaticPut,
-        util::{next_hour_timestamp, next_rotation_timestamp, replayer_log},
+        util::{
+            build_register_vk, build_signal_vk, build_slash_pk, build_slash_vk,
+            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},
-    zk::{empty_witnesses, VerifyingKey, ZkCircuit},
-    zkas::ZkBinary,
+    zk::{ProvingKey, VerifyingKey},
     Error, Result,
     Error, Result,
 };
 };
 
 
@@ -101,10 +103,6 @@ pub const NULL_PARENTS: [Hash; N_EVENT_PARENTS] = [NULL_ID; N_EVENT_PARENTS];
 /// Maximum number of DAGs to store, this should be configurable
 /// Maximum number of DAGs to store, this should be configurable
 pub const DAGS_MAX_NUMBER: i8 = 24;
 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.
 /// Atomic pointer to an [`EventGraph`] instance.
 pub type EventGraphPtr = Arc<EventGraph>;
 pub type EventGraphPtr = Arc<EventGraph>;
 pub type LayerUTips = BTreeMap<u64, HashSet<blake3::Hash>>;
 pub type LayerUTips = BTreeMap<u64, HashSet<blake3::Hash>>;
@@ -377,8 +375,12 @@ pub struct EventGraph {
     register_vk: VerifyingKey,
     register_vk: VerifyingKey,
     /// Signaling verify key
     /// Signaling verify key
     signal_vk: VerifyingKey,
     signal_vk: VerifyingKey,
+    /// Slashing proving key
+    slash_pk: ProvingKey,
     /// Slashing verify key
     /// Slashing verify key
     slash_vk: VerifyingKey,
     slash_vk: VerifyingKey,
+    /// RLN identity storage
+    pub rln_identity_tree: RwLock<SmtMemoryFp>,
 }
 }
 
 
 impl EventGraph {
 impl EventGraph {
@@ -403,65 +405,14 @@ impl EventGraph {
         hours_rotation: u64,
         hours_rotation: u64,
         ex: Arc<Executor<'_>>,
         ex: Arc<Executor<'_>>,
     ) -> Result<EventGraphPtr> {
     ) -> Result<EventGraphPtr> {
-        // Read or build signal verifying key
-        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
-            }
-        };
+        let register_vk = build_register_vk(&sled_db)?;
+        let signal_vk = build_signal_vk(&sled_db)?;
+        let slash_pk = build_slash_pk(&sled_db)?;
+        let slash_vk = build_slash_vk(&sled_db)?;
 
 
-        // 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);
-
-        let signal_vk = match sled_db.get("rlnv2-diff-signal-vk")? {
-            Some(vk) => {
-                let mut reader = Cursor::new(vk);
-                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)?;
-                verifyingkey
-            }
-        };
-
-        // 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 hasher = PoseidonFp::new();
+        let store = MemoryStorageFp::new();
+        let identity_tree = SmtMemoryFp::new(store, hasher.clone(), &EMPTY_NODES_FP);
 
 
         let broadcasted_ids = RwLock::new(HashSet::new());
         let broadcasted_ids = RwLock::new(HashSet::new());
         let event_pub = Publisher::new();
         let event_pub = Publisher::new();
@@ -498,7 +449,9 @@ impl EventGraph {
             deg_publisher: Publisher::new(),
             deg_publisher: Publisher::new(),
             register_vk,
             register_vk,
             signal_vk,
             signal_vk,
+            slash_pk,
             slash_vk,
             slash_vk,
+            rln_identity_tree: RwLock::new(identity_tree),
         });
         });
 
 
         // Check if we have it in our DAG.
         // Check if we have it in our DAG.

+ 2 - 2
src/event_graph/proof/rlnv2-diff-register.zk

@@ -7,7 +7,7 @@ witness "Rlnv2Diff_Register" {
 	Base identity_nullifier,
 	Base identity_nullifier,
 	Base identity_trapdoor,
 	Base identity_trapdoor,
 	Base user_message_limit,
 	Base user_message_limit,
-	Base message_limit,
+	Base max_message_limit,
 }
 }
 
 
 circuit "Rlnv2Diff_Register" {
 circuit "Rlnv2Diff_Register" {
@@ -15,7 +15,7 @@ circuit "Rlnv2Diff_Register" {
 	identity_secret_hash = poseidon_hash(identity_secret, user_message_limit);
 	identity_secret_hash = poseidon_hash(identity_secret, user_message_limit);
 	identity_commitment = poseidon_hash(identity_secret_hash);
 	identity_commitment = poseidon_hash(identity_secret_hash);
 
 
-	less_than_strict(user_message_limit, message_limit);
+	less_than_strict(user_message_limit, max_message_limit);
 
 
 	constrain_instance(identity_commitment);
 	constrain_instance(identity_commitment);
 	constrain_instance(user_message_limit);
 	constrain_instance(user_message_limit);

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

@@ -11,6 +11,8 @@ witness "Rlnv2Diff_Slash" {
 }
 }
 
 
 circuit "Rlnv2Diff_Slash" {
 circuit "Rlnv2Diff_Slash" {
+	constrain_instance(secret_key);
+	constrain_instance(user_message_limit);
 	identity_secret_hash = poseidon_hash(secret_key, user_message_limit);
 	identity_secret_hash = poseidon_hash(secret_key, user_message_limit);
 	identity_commitment = poseidon_hash(identity_secret_hash);
 	identity_commitment = poseidon_hash(identity_secret_hash);
 	root = sparse_merkle_root(identity_commitment, path, identity_commitment);
 	root = sparse_merkle_root(identity_commitment, path, identity_commitment);

+ 79 - 19
src/event_graph/proto.rs

@@ -31,14 +31,17 @@ use darkfi_sdk::{
     pasta::{pallas, Fp},
     pasta::{pallas, Fp},
 };
 };
 use darkfi_serial::{
 use darkfi_serial::{
-    async_trait, deserialize_async, deserialize_async_partial, SerialDecodable, SerialEncodable,
+    async_trait, deserialize_async, deserialize_async_partial, serialize_async, SerialDecodable,
+    SerialEncodable,
 };
 };
 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, Event, EventGraphPtr, LayerUTips, NULL_ID, NULL_PARENTS};
 use crate::{
 use crate::{
-    event_graph::util::{closest_epoch, hash_event, sss_recover, MessageMetadata},
+    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},
@@ -305,11 +308,11 @@ impl ProtocolEventGraph {
                 if blob.is_empty() {
                 if blob.is_empty() {
                     break
                     break
                 }
                 }
-                let (proof, y, internal_nullifier, identity_root): (
+                let (proof, y, internal_nullifier, user_msg_limit): (
                     Proof,
                     Proof,
                     pallas::Base,
                     pallas::Base,
                     pallas::Base,
                     pallas::Base,
-                    pallas::Base,
+                    u64,
                 ) = match deserialize_async_partial(&blob).await {
                 ) = match deserialize_async_partial(&blob).await {
                     Ok((v, _)) => v,
                     Ok((v, _)) => v,
                     Err(e) => {
                     Err(e) => {
@@ -328,26 +331,48 @@ impl ProtocolEventGraph {
                 let epoch = pallas::Base::from(current_epoch);
                 let epoch = pallas::Base::from(current_epoch);
                 let external_nullifier = poseidon_hash([epoch, rln_app_identifier]);
                 let external_nullifier = poseidon_hash([epoch, rln_app_identifier]);
                 let x = hash_event(&event);
                 let x = hash_event(&event);
+                let identity_root = self.event_graph.rln_identity_tree.read().await.root();
                 let public_inputs =
                 let public_inputs =
                     vec![identity_root, external_nullifier, x, y, internal_nullifier];
                     vec![identity_root, external_nullifier, x, y, internal_nullifier];
 
 
                 if metadata.is_duplicate(&external_nullifier, &internal_nullifier, &x, &y) {
                 if metadata.is_duplicate(&external_nullifier, &internal_nullifier, &x, &y) {
-                    error!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Duplicate Message!");
+                    error!(target: "event_graph::protocol::handle_event_put()", "[RLN] Duplicate Message!");
                     verification_failed = true;
                     verification_failed = true;
                     break
                     break
                 }
                 }
 
 
-                info!("internal nullifier: {}", internal_nullifier.to_string());
                 if metadata.is_reused(&external_nullifier, &internal_nullifier) {
                 if metadata.is_reused(&external_nullifier, &internal_nullifier) {
-                    info!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Metadata is reused.. slashing..");
+                    info!(target: "event_graph::protocol::handle_event_put()", "[RLN] Metadata is reused.. slashing..");
                     let shares = metadata.get_shares(&external_nullifier, &internal_nullifier);
                     let shares = metadata.get_shares(&external_nullifier, &internal_nullifier);
-                    let _secret = sss_recover(&shares);
+                    let secret = sss_recover(&shares);
+
+                    // Broadcast slashing event
+                    let slash_pk = &self.event_graph.slash_pk;
+                    let mut identity_tree = self.event_graph.rln_identity_tree.write().await;
+
+                    info!("[RLN] Creating slashing proof");
+                    let (proof, identity_root) = match create_slash_proof(
+                        secret,
+                        user_msg_limit,
+                        &mut identity_tree,
+                        slash_pk,
+                    ) {
+                        Ok(v) => v,
+                        Err(e) => {
+                            error!("[RLN] Failed creating RLN slash proof: {}", e);
+                            // Just use an empty "proof"
+                            (Proof::new(vec![]), pallas::Base::from(0))
+                        }
+                    };
+                    drop(identity_tree);
+
+                    let blob =
+                        serialize_async(&(proof, secret, user_msg_limit, identity_root)).await;
+
+                    let evgr = &self.event_graph;
+                    let st_event = Event::new_static(vec![0, 1], evgr).await;
+                    evgr.static_broadcast(st_event, blob).await?;
 
 
-                    // TODO: broadcast slashing event
-                    // let evgr = &self.event_graph;
-                    // let st_event = Event::new_static(serialize_async(&secret).await, evgr).await;
-                    // evgr.static_insert(&st_event).await?;
-                    // evgr.static_broadcast(st_event);
                     verification_failed = true;
                     verification_failed = true;
                     break
                     break
                 }
                 }
@@ -355,7 +380,7 @@ impl ProtocolEventGraph {
                 // At this point we can safely add the shares
                 // At this point we can safely add the shares
                 metadata.add_share(external_nullifier, internal_nullifier, x, y)?;
                 metadata.add_share(external_nullifier, internal_nullifier, x, y)?;
 
 
-                info!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Verifying incoming Event RLN proof");
+                info!(target: "event_graph::protocol::handle_event_put()", "[RLN] Verifying incoming Event RLN proof");
                 verification_failed =
                 verification_failed =
                     proof.verify(&self.event_graph.signal_vk, &public_inputs).is_err();
                     proof.verify(&self.event_graph.signal_vk, &public_inputs).is_err();
 
 
@@ -363,7 +388,7 @@ impl ProtocolEventGraph {
             }
             }
 
 
             if verification_failed {
             if verification_failed {
-                error!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Incoming Event RLN Signaling proof verification failed");
+                error!(target: "event_graph::protocol::handle_event_put()", "[RLN] Incoming Event RLN Signaling proof verification failed");
                 continue
                 continue
             }
             }
 
 
@@ -647,13 +672,14 @@ impl ProtocolEventGraph {
                 continue
                 continue
             }
             }
 
 
-            if !blob.is_empty() {
+            // Register
+            if !blob.is_empty() && !event.content().is_empty() {
                 let (proof, user_msg_limit): (Proof, u64) = match deserialize_async_partial(&blob)
                 let (proof, user_msg_limit): (Proof, u64) = match deserialize_async_partial(&blob)
                     .await
                     .await
                 {
                 {
                     Ok((v, _)) => v,
                     Ok((v, _)) => v,
                     Err(e) => {
                     Err(e) => {
-                        error!(target: "event_graph::protocol::handle_static_put()","[EVENTGRAPH] Failed deserializing event ephemeral data: {}", e);
+                        error!(target: "event_graph::protocol::handle_static_put()","[RLN] Failed deserializing event ephemeral data: {}", e);
                         continue
                         continue
                     }
                     }
                 };
                 };
@@ -664,13 +690,47 @@ impl ProtocolEventGraph {
                         continue
                         continue
                     }
                     }
                 };
                 };
+                info!("registering account: {}", commitment.to_string());
                 let public_inputs = vec![commitment, user_msg_limit.into()];
                 let public_inputs = vec![commitment, user_msg_limit.into()];
 
 
                 if proof.verify(&self.event_graph.register_vk, &public_inputs).is_err() {
                 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");
+                    error!(target: "event_graph::protocol::handle_static_put()", "[RLN] Incoming Event RLN Registration proof verification failed");
                     continue
                     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);
+                        continue
+                    }
+                };
+
+                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
+                }
+
+                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 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
             for parent in event.header.parents.iter() {
             for parent in event.header.parents.iter() {
                 if *parent == NULL_ID {
                 if *parent == NULL_ID {
@@ -740,7 +800,7 @@ impl ProtocolEventGraph {
             // If we do have it, we will send it back to them as `EventRep`.
             // If we do have it, we will send it back to them as `EventRep`.
             // Otherwise, we'll stay quiet. An honest node should always have
             // Otherwise, we'll stay quiet. An honest node should always have
             // something to reply with provided that the request is legitimate,
             // something to reply with provided that the request is legitimate,
-            // i.e. we've sent something to them and they did not have some of
+            // i.e. we've sent something to them and they did not haveinfo some of
             // the parents.
             // the parents.
 
 
             // Check if we expected this request to come around.
             // Check if we expected this request to come around.

+ 134 - 11
src/event_graph/util.rs

@@ -19,35 +19,42 @@
 use std::{
 use std::{
     collections::{BTreeMap, HashMap},
     collections::{BTreeMap, HashMap},
     fs::{self, File, OpenOptions},
     fs::{self, File, OpenOptions},
-    io::Write,
+    io::{Cursor, Write},
     path::Path,
     path::Path,
     time::UNIX_EPOCH,
     time::UNIX_EPOCH,
 };
 };
 
 
-use darkfi_sdk::{crypto::pasta_prelude::FromUniformBytes, pasta::pallas};
+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;
+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;
+use tracing::{error, info};
 
 
 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,
+    util::{encoding::base64, file::load_file},
+    zk::{empty_witnesses, Proof, ProvingKey, VerifyingKey, Witness, ZkCircuit},
+    zkas::ZkBinary,
     Result,
     Result,
 };
 };
 
 
 #[cfg(feature = "rpc")]
 #[cfg(feature = "rpc")]
-use crate::{
-    rpc::{
-        jsonrpc::{ErrorCode, JsonError, JsonResponse, JsonResult},
-        util::json_map,
-    },
-    util::file::load_file,
+use crate::rpc::{
+    jsonrpc::{ErrorCode, JsonError, JsonResponse, JsonResult},
+    util::json_map,
 };
 };
 
 
 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
 /// RLN epoch genesis in millis
 pub const RLN_GENESIS: u64 = 1_738_688_400_000;
 pub const RLN_GENESIS: u64 = 1_738_688_400_000;
 /// RLN epoch length in millis
 /// RLN epoch length in millis
@@ -311,6 +318,36 @@ impl MessageMetadata {
     }
     }
 }
 }
 
 
+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
 /// Recover secret using Shamir's secret sharing scheme
 pub fn sss_recover(shares: &[(pallas::Base, pallas::Base)]) -> pallas::Base {
 pub fn sss_recover(shares: &[(pallas::Base, pallas::Base)]) -> pallas::Base {
     let mut secret = pallas::Base::zero();
     let mut secret = pallas::Base::zero();
@@ -329,6 +366,92 @@ pub fn sss_recover(shares: &[(pallas::Base, pallas::Base)]) -> pallas::Base {
     secret
     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::*;