Просмотр исходного кода

darkirc: Add RLN proof verification on incoming events

parazyd 1 год назад
Родитель
Сommit
868306637b
3 измененных файлов с 110 добавлено и 20 удалено
  1. 3 2
      bin/darkirc/src/crypto/rln.rs
  2. 77 4
      bin/darkirc/src/irc/client.rs
  3. 30 14
      bin/darkirc/src/irc/server.rs

+ 3 - 2
bin/darkirc/src/crypto/rln.rs

@@ -99,7 +99,7 @@ impl RlnIdentity {
         event: &Event,
         event: &Event,
         identity_tree: &MerkleTree,
         identity_tree: &MerkleTree,
         identity_pos: Position,
         identity_pos: Position,
-        proving_key: ProvingKey,
+        proving_key: &ProvingKey,
     ) -> Result<(Proof, Vec<pallas::Base>)> {
     ) -> Result<(Proof, Vec<pallas::Base>)> {
         // 1. Construct share
         // 1. Construct share
         let epoch = pallas::Base::from(closest_epoch(event.timestamp));
         let epoch = pallas::Base::from(closest_epoch(event.timestamp));
@@ -136,12 +136,13 @@ impl RlnIdentity {
         let signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN)?;
         let signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN)?;
         let signal_circuit = ZkCircuit::new(witnesses, &signal_zkbin);
         let signal_circuit = ZkCircuit::new(witnesses, &signal_zkbin);
 
 
-        let proof = Proof::create(&proving_key, &[signal_circuit], &public_inputs, &mut OsRng)?;
+        let proof = Proof::create(proving_key, &[signal_circuit], &public_inputs, &mut OsRng)?;
         Ok((proof, vec![y, internal_nullifier]))
         Ok((proof, vec![y, internal_nullifier]))
     }
     }
 }
 }
 
 
 /// Recover a secret from given secret shares
 /// Recover a secret from given secret shares
+#[allow(dead_code)]
 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();
     for (j, share_j) in shares.iter().enumerate() {
     for (j, share_j) in shares.iter().enumerate() {

+ 77 - 4
bin/darkirc/src/irc/client.rs

@@ -34,12 +34,12 @@ use darkfi::{
 };
 };
 use darkfi_sdk::{
 use darkfi_sdk::{
     bridgetree::Position,
     bridgetree::Position,
-    crypto::{pasta_prelude::PrimeField, MerkleTree},
+    crypto::{pasta_prelude::PrimeField, poseidon_hash, MerkleTree},
     pasta::pallas,
     pasta::pallas,
 };
 };
 use darkfi_serial::{deserialize_async, serialize_async};
 use darkfi_serial::{deserialize_async, serialize_async};
 use futures::FutureExt;
 use futures::FutureExt;
-use log::{debug, error, warn};
+use log::{debug, error, info, warn};
 use sled_overlay::sled;
 use sled_overlay::sled;
 use smol::{
 use smol::{
     io::{self, AsyncBufReadExt, AsyncWriteExt, BufReader},
     io::{self, AsyncBufReadExt, AsyncWriteExt, BufReader},
@@ -52,7 +52,9 @@ use super::{
     server::{IrcServer, MAX_MSG_LEN},
     server::{IrcServer, MAX_MSG_LEN},
     Msg, NickServ, OldPrivmsg, SERVER_NAME,
     Msg, NickServ, OldPrivmsg, SERVER_NAME,
 };
 };
-use crate::crypto::rln::{closest_epoch, RlnIdentity, RLN2_SIGNAL_ZKBIN};
+use crate::crypto::rln::{
+    closest_epoch, hash_event, RlnIdentity, RLN2_SIGNAL_ZKBIN, RLN_APP_IDENTIFIER,
+};
 
 
 const PENALTY_LIMIT: usize = 5;
 const PENALTY_LIMIT: usize = 5;
 
 
@@ -259,6 +261,49 @@ impl Client {
                         }
                         }
                     }
                     }
 
 
+                    // If the Event contains an appended blob of data, try to check if it's
+                    // a RLN Signal proof and verify it.
+                    //if false {
+                    let mut verification_failed = false;
+                    #[allow(clippy::never_loop)]
+                    loop {
+                        let (event, blob) = (r.clone(), vec![0,1,2]);
+                        let (proof, public_inputs): (Proof, Vec<pallas::Base>) = match deserialize_async(&blob).await {
+                            Ok(v) => v,
+                            Err(e) => {
+                                // TODO: FIXME: This logic should be better written.
+                                // Right now we don't enforce RLN so we can just fall-through.
+                                //error!("[IRC CLIENT] Failed deserializing event ephemeral data: {}", e);
+                                break
+                            }
+                        };
+
+                        if public_inputs.len() != 2 {
+                            error!("[IRC CLIENT] Received event has the wrong number of public inputs");
+                            verification_failed = true;
+                            break
+                        }
+
+                        info!("[IRC CLIENT] Verifying incoming Event RLN proof");
+                        if self.verify_rln_signal_proof(
+                            &event,
+                            proof,
+                            [public_inputs[0], public_inputs[1]],
+                        ).await.is_err() {
+                            verification_failed = true;
+                            break
+                        }
+
+                        // TODO: Store for secret shares recovery
+                        info!("[IRC CLIENT] RLN verification successful");
+                        break
+                    }
+
+                    if verification_failed {
+                        error!("[IRC CLIENT] Incoming Event proof verification failed");
+                        continue
+                    }
+
                     // Try to deserialize the `Event`'s content into a `Privmsg`
                     // Try to deserialize the `Event`'s content into a `Privmsg`
                     let mut privmsg = match Msg::deserialize(r.content()).await {
                     let mut privmsg = match Msg::deserialize(r.content()).await {
                         Ok(Msg::V1(old_msg)) => old_msg.into_new(),
                         Ok(Msg::V1(old_msg)) => old_msg.into_new(),
@@ -558,6 +603,34 @@ impl Client {
         let mut reader = Cursor::new(proving_key);
         let mut reader = Cursor::new(proving_key);
         let proving_key = ProvingKey::read(&mut reader, signal_circuit)?;
         let proving_key = ProvingKey::read(&mut reader, signal_circuit)?;
 
 
-        rln_identity.create_signal_proof(event, &identity_tree, identity_pos, proving_key)
+        rln_identity.create_signal_proof(event, &identity_tree, identity_pos, &proving_key)
+    }
+
+    /// Abstraction for RLN signal proof verification
+    async fn verify_rln_signal_proof(
+        &self,
+        event: &Event,
+        proof: Proof,
+        public_inputs: [pallas::Base; 2],
+    ) -> Result<()> {
+        let epoch = pallas::Base::from(closest_epoch(event.timestamp));
+        let external_nullifier = poseidon_hash([epoch, RLN_APP_IDENTIFIER]);
+        let x = hash_event(event);
+        let y = public_inputs[0];
+        let internal_nullifier = public_inputs[1];
+
+        // Fetch the latest commitment Merkle tree
+        let Some(identity_tree) = self.server.server_store.get("rln_identity_tree")? else {
+            return Err(Error::DatabaseError(
+                "RLN Identity tree not found in server store".to_string(),
+            ))
+        };
+        let identity_tree: MerkleTree = deserialize_async(&identity_tree).await?;
+        let identity_root = identity_tree.root(0).unwrap();
+
+        let public_inputs =
+            vec![epoch, external_nullifier, x, y, internal_nullifier, identity_root.inner()];
+
+        Ok(proof.verify(&self.server.rln_signal_vk, &public_inputs)?)
     }
     }
 }
 }

+ 30 - 14
bin/darkirc/src/irc/server.rs

@@ -16,7 +16,13 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
  */
 
 
-use std::{collections::HashMap, fs::File, io::BufReader, path::PathBuf, sync::Arc};
+use std::{
+    collections::HashMap,
+    fs::File,
+    io::{BufReader, Cursor},
+    path::PathBuf,
+    sync::Arc,
+};
 
 
 use darkfi::{
 use darkfi::{
     event_graph::Event,
     event_graph::Event,
@@ -90,6 +96,8 @@ pub struct IrcServer {
     pub server_store: sled::Tree,
     pub server_store: sled::Tree,
     /// RLN identity storage
     /// RLN identity storage
     pub rln_identity_store: sled::Tree,
     pub rln_identity_store: sled::Tree,
+    /// RLN Signal VerifyingKey
+    pub rln_signal_vk: VerifyingKey,
 }
 }
 
 
 impl IrcServer {
 impl IrcServer {
@@ -149,25 +157,32 @@ impl IrcServer {
         let rln_identity_store = darkirc.sled.open_tree("rln_identity_store")?;
         let rln_identity_store = darkirc.sled.open_tree("rln_identity_store")?;
 
 
         // 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_circuit =
+            ZkCircuit::new(empty_witnesses(&rln_signal_zkbin)?, &rln_signal_zkbin);
+
         if server_store.get("rlnv2-diff-signal-pk")?.is_none() {
         if server_store.get("rlnv2-diff-signal-pk")?.is_none() {
             info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Signal ProvingKey");
             info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Signal ProvingKey");
-            let zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN)?;
-            let circuit = ZkCircuit::new(empty_witnesses(&zkbin).unwrap(), &zkbin);
-            let provingkey = ProvingKey::build(zkbin.k, &circuit);
+            let provingkey = ProvingKey::build(rln_signal_zkbin.k, &rln_signal_circuit);
             let mut buf = vec![];
             let mut buf = vec![];
             provingkey.write(&mut buf)?;
             provingkey.write(&mut buf)?;
             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 zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN)?;
-            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-signal-vk", buf)?;
-        }
+        let rln_signal_vk = match server_store.get("rlnv2-diff-signal-vk")? {
+            Some(vk) => {
+                let mut reader = Cursor::new(vk);
+                VerifyingKey::read(&mut reader, rln_signal_circuit)?
+            }
+            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)?;
+                verifyingkey
+            }
+        };
 
 
         if server_store.get("rlnv2-diff-slash-pk")?.is_none() {
         if server_store.get("rlnv2-diff-slash-pk")?.is_none() {
             info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash ProvingKey");
             info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash ProvingKey");
@@ -191,7 +206,7 @@ impl IrcServer {
 
 
         // Initialize RLN Incremental Merkle tree if necessary
         // Initialize RLN Incremental Merkle tree if necessary
         if server_store.get("rln_identity_tree")?.is_none() {
         if server_store.get("rln_identity_tree")?.is_none() {
-            let tree = MerkleTree::new(0);
+            let tree = MerkleTree::new(1);
             server_store.insert("rln_identity_tree", serialize_async(&tree).await)?;
             server_store.insert("rln_identity_tree", serialize_async(&tree).await)?;
         }
         }
 
 
@@ -209,6 +224,7 @@ impl IrcServer {
             password,
             password,
             server_store,
             server_store,
             rln_identity_store,
             rln_identity_store,
+            rln_signal_vk,
         });
         });
 
 
         // Load any channel/contact configuration.
         // Load any channel/contact configuration.