mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
darkirc: Add RLN proof verification on incoming events
This commit is contained in:
@@ -99,7 +99,7 @@ impl RlnIdentity {
|
||||
event: &Event,
|
||||
identity_tree: &MerkleTree,
|
||||
identity_pos: Position,
|
||||
proving_key: ProvingKey,
|
||||
proving_key: &ProvingKey,
|
||||
) -> Result<(Proof, Vec<pallas::Base>)> {
|
||||
// 1. Construct share
|
||||
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_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]))
|
||||
}
|
||||
}
|
||||
|
||||
/// Recover a secret from given secret shares
|
||||
#[allow(dead_code)]
|
||||
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() {
|
||||
|
||||
@@ -34,12 +34,12 @@ use darkfi::{
|
||||
};
|
||||
use darkfi_sdk::{
|
||||
bridgetree::Position,
|
||||
crypto::{pasta_prelude::PrimeField, MerkleTree},
|
||||
crypto::{pasta_prelude::PrimeField, poseidon_hash, MerkleTree},
|
||||
pasta::pallas,
|
||||
};
|
||||
use darkfi_serial::{deserialize_async, serialize_async};
|
||||
use futures::FutureExt;
|
||||
use log::{debug, error, warn};
|
||||
use log::{debug, error, info, warn};
|
||||
use sled_overlay::sled;
|
||||
use smol::{
|
||||
io::{self, AsyncBufReadExt, AsyncWriteExt, BufReader},
|
||||
@@ -52,7 +52,9 @@ use super::{
|
||||
server::{IrcServer, MAX_MSG_LEN},
|
||||
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;
|
||||
|
||||
@@ -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`
|
||||
let mut privmsg = match Msg::deserialize(r.content()).await {
|
||||
Ok(Msg::V1(old_msg)) => old_msg.into_new(),
|
||||
@@ -558,6 +603,34 @@ impl Client {
|
||||
let mut reader = Cursor::new(proving_key);
|
||||
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)?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,13 @@
|
||||
* 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::{
|
||||
event_graph::Event,
|
||||
@@ -90,6 +96,8 @@ pub struct IrcServer {
|
||||
pub server_store: sled::Tree,
|
||||
/// RLN identity storage
|
||||
pub rln_identity_store: sled::Tree,
|
||||
/// RLN Signal VerifyingKey
|
||||
pub rln_signal_vk: VerifyingKey,
|
||||
}
|
||||
|
||||
impl IrcServer {
|
||||
@@ -149,25 +157,32 @@ impl IrcServer {
|
||||
let rln_identity_store = darkirc.sled.open_tree("rln_identity_store")?;
|
||||
|
||||
// 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() {
|
||||
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![];
|
||||
provingkey.write(&mut 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() {
|
||||
info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash ProvingKey");
|
||||
@@ -191,7 +206,7 @@ impl IrcServer {
|
||||
|
||||
// Initialize RLN Incremental Merkle tree if necessary
|
||||
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)?;
|
||||
}
|
||||
|
||||
@@ -209,6 +224,7 @@ impl IrcServer {
|
||||
password,
|
||||
server_store,
|
||||
rln_identity_store,
|
||||
rln_signal_vk,
|
||||
});
|
||||
|
||||
// Load any channel/contact configuration.
|
||||
|
||||
Reference in New Issue
Block a user